无法从控制器通过/更新ngModel到指令 [英] Unable to pass/update ngModel from controller to directive

查看:225
本文介绍了无法从控制器通过/更新ngModel到指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的UI插件的选择,我路过纳克模型从我的控制器称为richSelect自定义指令,但NG-模型不似乎得到更新选择任何项目。

 < richselect NG模型=数据模型>< / richselect>

自定义指令

  app.directive('richselect',['$编译,函数($编译){
返回{
    限制:AE,
    范围: {
        ngModel:'='/ *与对象相关联*型号/
    },
    链接:功能(范围,元素,ATTRS,ngModel){
        scope.options = [
                         {
                             值:VALUE1,
                             说明:值一号
                         },
                         {
                             '值':'值',
                             说明:值的两个
                         }
        ]
        scope.getRichSelectTemplate =功能(){            回归'< UI选多个NG模型=ngModel主题=引导NG-禁用=禁用>' +
            {{ngModel}}< UI的选择匹配占位=选择> {{$ select.selected.Desc}}< / UI选匹配>' +
                '< UI的选择,选择重复=,在选项选项|过滤器:$ select.search>' +
                        '<跨度NG绑定-HTML =option.Desc |亮点:$ select.search>< / SPAN>' +
                '< / UI的选择,选择>' +
            '< / UI选>';
        }         VAR linkFn = $编译(scope.getRichSelectTemplate())(范围);
         element.append(linkFn);
    }
}
}]);

Plnkr: http://plnkr.co/edit/Im8gpxEwnU7sgrKgqZXY?p=preVIEW


解决方案

下面,试试这个。我不完全相信你试图得到什么格式或输出,但是这得到所选的选项传递给视图。


  • 修改 - 我摆脱了曾经是这里的plunker的

您必须使用 ngModel。$ setViewValue ,以改变在视图中的指令NG-模式的价值。此外,获得的价值UI的选择,你需要有NG-模型指着 options.selected

然后,它只是一个增加一个 NG-点击这指出了更新的观点与 ngModel功能的问题。$ setViewValue(范围.options.selected

另外,我相信你需要`要求:ngModel在你的指令,以便您可以访问ngModelController

  app.directive('richselect',['$编译,函数($编译){
    返回{
        限制:AE,
        要求:'ngModel',
        范围: {
            胡说:'='/ *与对象相关联*型号/
        },
        链接:功能(范围,元素,ATTRS,ngModel){
          scope.changer =功能(){
            ngModel。$ setViewValue(scope.options.selected)
            的console.log(scope.options.selected)
          }
            scope.options = [
                             {
                                 值:VALUE1,
                                 说明:值一号
                             },
                             {
                                 '值':'值',
                                 说明:值的两个
                             }
            ]
            scope.getRichSelectTemplate =功能(){                回归'< UI选多个NG模型=options.selected主题=引导NG点击=换碟机()NG-禁用=禁用>' +
                {{options.selected}}< UI的选择匹配占位=选择> {{$ select.selected.Desc}}< / UI选匹配>' +
                    '< UI的选择,选择重复=,在选项选项|过滤器:$ select.search>' +
                            '<跨度NG绑定-HTML =option.Desc |亮点:$ select.search>< / SPAN>' +
                    '< / UI的选择,选择>' +
                '< / UI选>';
            }             VAR linkFn = $编译(scope.getRichSelectTemplate())(范围);
             element.append(linkFn);
        }
    }
}]);

编辑:
很多挖掘和修补,每下面的评论后 - 让双向绑定工作已证明有些难以捉摸。我发现这是很容易使用标准的用户界面,选择指令做,因为在这里看到(例如修改code从UI选择),因为我们可以很容易地访问指令的适用范围:
标准指令演示

我也碰到了类似的包装作为一个在OP,但与它玩耍后,那人似乎有同样的问题 - 它很容易得到的东西,但是如果你需要将数据推入指令它不想去。
有趣的是,在我上面的解决方案,我可以看到`scope.options.selected'对象实际上包含的数据,只是从来没有下来的UI选指令的范围,因此从来没有允许我们在推送数据。

遇到了类似的问题在一个项目中我的工作在不同的包装指令后,我想通了,如何通过不同的范围将数据推了下来。

我的解决办法是修改UI选脚本本身,并称一个变量在它的 $父检查范围内$监控功能。由于UI的选择指令使用范围:真正的,它会创建一个子作用域(其中,如果我没有记错的话,家长会在这个OP指令)<。 / p>

唐氏在uiSelect指令的链接功能的底部添加以下的手表功能:

 范围。$表(函数(){
  返回范围$ parent.myVar。
},功能(的newval){
  $ select.selected =的newval;
})

在这里我们directve的链接功能,我添加了这个$​​腕表功能:

 范围。$表(函数(){
  返回ngModel $ viewValue。
},功能(的newval){
  scope.myVar =的newval;
})

所以,这里所发生的是,如果$ viewValue变化(即我们从一个HTTP服务,等来了数据模型绑定,$手表功能分配一些数据会抓住它,并把它分配给scope.myVar,与UI选择脚本中的$手表功能的手表范围。$ parent.myVar更改(我们告诉它看在它的父范围的变量)。如果它看到这促使他们任何修改 $ select.selected - 这是用户界面,选择保留已选定的任何值,通过单击某个项目下拉列表。我们只是重写,并插入我们想要的任何值。

Plunker - 双向绑定

I'm using ui-select plugin and I'm passing ng-model from my controller to a custom directive called richSelect but the ng-model doesn't seemed to get updated on select of any item.

<richselect ng-model="dataModel"></richselect>

Custom directive

app.directive('richselect', ['$compile', function ($compile) {
return {
    restrict: 'AE',
    scope: {
        ngModel: '='               /* Model associated with the object */
    },
    link: function (scope, element, attrs, ngModel) {
        scope.options = [
                         {
                             'Value' : 'value1',
                             'Desc' : 'Value One'
                         },
                         {
                             'Value' : 'value2',
                             'Desc' : 'Value Two'
                         }
        ]
        scope.getRichSelectTemplate = function () {

            return '<ui-select multiple ng-model="ngModel" theme="bootstrap"  ng-disabled="disabled">' +
            '{{ngModel}} <ui-select-match placeholder="Select">{{$select.selected.Desc}}</ui-select-match>' +
                '<ui-select-choices repeat="option in options | filter: $select.search">' +
                        '<span ng-bind-html="option.Desc | highlight: $select.search"></span>' +
                '</ui-select-choices>' +
            '</ui-select>';
        }       

         var linkFn = $compile(scope.getRichSelectTemplate())(scope);
         element.append(linkFn);
    }
}
}]);

Plnkr : http://plnkr.co/edit/Im8gpxEwnU7sgrKgqZXY?p=preview

解决方案

Here, try this. I wasn't exactly sure what format or output you were trying to get, but this gets the selected options passed to the View.

  • EDIT - I got rid of the plunker that used to be here.

You have to use the ngModel.$setViewValue in order to change the value of ng-model in the directive in the view. Additionally, to get the value of the ui-select, you need to have ng-model pointed at the options.selected

Then it was just a matter of adding an ng-click that pointed to a function that updated the view with ngModel.$setViewValue(scope.options.selected.

Also, I believe you need to `require: 'ngModel' in your directive so you can access the ngModelController.

app.directive('richselect', ['$compile', function ($compile) {
    return {
        restrict: 'AE',
        require: 'ngModel',
        scope: {
            blah: '='               /* Model associated with the object */
        },
        link: function (scope, element, attrs, ngModel) {
          scope.changer = function() {
            ngModel.$setViewValue(scope.options.selected)
            console.log(scope.options.selected)
          }
            scope.options = [
                             {
                                 'Value' : 'value1',
                                 'Desc' : 'Value One'
                             },
                             {
                                 'Value' : 'value2',
                                 'Desc' : 'Value Two'
                             }
            ]
            scope.getRichSelectTemplate = function () {

                return '<ui-select multiple ng-model="options.selected" theme="bootstrap" ng-click="changer()" ng-disabled="disabled">' +
                '{{options.selected}} <ui-select-match placeholder="Select">{{$select.selected.Desc}}</ui-select-match>' +
                    '<ui-select-choices repeat="option in options | filter: $select.search">' +
                            '<span ng-bind-html="option.Desc | highlight: $select.search"></span>' +
                    '</ui-select-choices>' +
                '</ui-select>';
            }       

             var linkFn = $compile(scope.getRichSelectTemplate())(scope);
             element.append(linkFn);
        }
    }
}]); 

EDIT: After a lot of digging and tinkering, per the comment below - getting two-way binding working has proved somewhat elusive. I found it was quite easy to do using the standard ui-select directive, as seen here (modified example code from ui-select), because we can easily get access to the scope of the directive: Standard Directive Demo

I also came across a similar wrapper as the one in the OP, but after playing with it,that one seemed to have the same issue - it's easy to get stuff out, but if you need to push data into the directive it doesn't want to go. Interestingly, in my solution above, I can see that the `scope.options.selected' object actually contains the data, it just never gets down the the scope of the ui-select directive, and thus never allows us to push data in.

After encountering a similar issue with a different wrapper directive in a project I am working on, I figured out how to push data down through the different scopes.

My solution was to modify the ui-select script itself, adding an internal $watch function that checked for a variable in it's $parent scope. Since the ui-select directive uses scope: true, it creates a child scope (which, if I am not mistaken, the parent would be the directive in this OP).

Down at the bottom of the link function of the uiSelect directive I added the following watch function:

scope.$watch(function() {
  return scope.$parent.myVar;
}, function(newVal) {
  $select.selected = newVal;
})

In the link function of our directve here, I added this $watch function:

scope.$watch(function() {
  return ngModel.$viewValue;
}, function(newVal) {
  scope.myVar = newVal;
})

So what happens here is that if the $viewValue changes (i.e., we assign some data from a http service, etc. to the dataModel binding, the $watch function will catch it and assign it to scope.myVar. The $watch function inside the ui-select script watches scope.$parent.myVar for changes (We are telling it to watch a variable on the scope of it's parent). If it sees any changes it pushes them to $select.selected - THIS is where ui-select keeps whatever values that have been selected by clicking an item in the dropdown. We simply override that and insert whatever values we want.

Plunker - Two-way binding

这篇关于无法从控制器通过/更新ngModel到指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆