angularjs将包装指令中的ngModel传递给包装指令

Aun*_*Aun 7 javascript angularjs angularjs-directive

我是Angular的新手,仍然痛苦地围绕自定义指令.

我想重用这一点HTML

<ui-select ng-model="model.selectedLanguages" multiple search-enabled="true" theme="select2" style="width: 300px;">
    <ui-select-match placeholder="Pick one...">{{$item.name}}</ui-select-match>
    <ui-select-choices repeat="lang.id as lang in langs |filter: { name : $select.search }">
        <div ng-bind-html="lang.name | highlight: $select.search" ></div> 
    </ui-select-choices>
</ui-select>
Run Code Online (Sandbox Code Playgroud)

通过将其包装到我的自定义指令中:

<language-picker ng-model="model.selectedLanguages"/>
Run Code Online (Sandbox Code Playgroud)

这样的事情:

app.directive('languagePicker', function() {
            return {
                template : '<ui-select ng-model="**PARENT'S NGMODEL**" multiple search-enabled="true" theme="select2" style="width: 300px;"><ui-select-match >{{$item.name}}</ui-select-match><ui-select-choices repeat="lang.id as lang in langs | filter: { name : $select.search }"><div ng-bind-html="lang.name | highlight: $select.search"></div></ui-select-choices></ui-select>',
                restrict : 'E',
                require : 'ngModel',
                replace : true
                    ....
            };
        });
Run Code Online (Sandbox Code Playgroud)

但是如何将ngModel从my language-picker传递给ui-select指令?

UPDATE

使用下面的建议,我使用了ui-select,但外部模型根本没有更新,请参阅plnkr.co/edit/Y43dmMGIc5GxM9fLoNPW,可能是因为它的子范围和父范围保持不变?

更新2

我让它以一种对我来说很糟糕的复杂方式工作,因为我不知道为什么它"起作用"(参见控制器中发生的奇怪事情):

app.directive('languagePicker', function(LanguageService) {
            return {
                templateUrl : 'LanguagePickerTpl.html',
                restrict : 'E',
                scope : {
                    languages : '='
                }, 
                controller : function($scope, LanguageService) {
                    console.log($scope);
                    $scope.langs = LanguageService.get();
                    $scope.model = $scope;
                }

            };
        })
Run Code Online (Sandbox Code Playgroud)

模板:

<ui-select ng-model="model.languages" multiple search-enabled="true" 
  theme="select2" style="width: 300px;">
    <ui-select-match>{{$item.name}}</ui-select-match>
    <ui-select-choices repeat="lang.id as lang in langs | filter: { name : $select.search }">
      <div ng-bind-html="lang.name | highlight: $select.search"></div>
    </ui-select-choices>
  </ui-select>
Run Code Online (Sandbox Code Playgroud)

如果有人能解释发生了什么,我将非常高兴("工作"示例在这里 http://plnkr.co/edit/B53F9sc7UGkj0uxUpC17 )

Nik*_*los 14

ng-model有一些特殊的处理,看到这里的标题"自定义控制示例"下.步骤是:

  1. 我建议你使用隔离范围; 它使您的组件的界面更清晰,并使您免于副作用.在这种情况下,您想要传递可用选项(语言)列表:

    scope: {
        langs: '='
    }
    
    Run Code Online (Sandbox Code Playgroud)

    用法是:

    <language-picker ng-model="model.selectedLanguages" langs="langs"/>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您的指令要求(可能选择)ngModel:

    require: ['ngModel']
    
    Run Code Online (Sandbox Code Playgroud)
  3. 你覆盖ngModel$render方法,例如:

    link: function(scope,elem,attrs,ctrls) {
        var ngModelCtrl = ctrls[0];
        ngModelCtrl.$render = function() {
            ...
        };
    }
    
    Run Code Online (Sandbox Code Playgroud)

    render的逻辑负责将模型值(这里的那个:<language-picker ng-model="model.selectedLanguages"/>,ie model.selectedLanguages)传递给视图.我能想到的最简单的事情是使用隔离范围并将外部模型值传递给隔离范围的变量:

        ngModelCtrl.$render = function() {
            scope.innerSelection = ngModelCtrl.$viewValue;
        };
    
    Run Code Online (Sandbox Code Playgroud)

    将此变量绑定在模板中:

    <ui-select ng-model="innerSelection" ...>
        ...
    </ui-select>
    
    Run Code Online (Sandbox Code Playgroud)
  4. 最后,您必须确保对内部选择的更改将传播到外部模型:

        // still inside link()
        scope.$watch('innerSelection', function(newval, oldval) {
            if( newval != oldval ) { // skip the first time
                ngModelCtrl.$setViewValue(newval);
            }
        });
    
    Run Code Online (Sandbox Code Playgroud)

此解决方案可能比其他解决方案更复杂,但允许您使用所有功能ngModel,例如验证,解析/格式化(即数据转换).


JDT*_*LH9 4

您需要在指令的范围内使用“等于”语法。这将保留父范围中填充的值。所以你的指令变成:

app.directive('languagePicker', function() {
        return {
            template : '<ui-select ng-model="**PARENT'S NGMODEL**" multiple search-enabled="true" theme="select2" style="width: 300px;"><ui-select-match >{{$item.name}}</ui-select-match><ui-select-choices repeat="lang.id as lang in langs | filter: { name : $select.search }"><div ng-bind-html="lang.name | highlight: $select.search"></div></ui-select-choices></ui-select>',
            restrict : 'E',
            require : 'ngModel',
            replace : true,
            scope: {
                ngModel: "=ngModel"
            }
            ...
        };
    });
Run Code Online (Sandbox Code Playgroud)

我相信这对您有用:) 如果不起作用请告诉我!

  • 我让它以一种极其复杂的方式工作,我不知道它为什么起作用http://plnkr.co/edit/B53F9sc7UGkj0uxUpC17 (2认同)