Angular directive: using ng-model within isolate scope

流过昼夜 提交于 2019-12-10 12:38:06

问题


I'm having trouble working out how I can define a custom directive that both:

  1. Uses isolate scope, and
  2. Uses the ng-model directive in a new scope within in its template.

Here's an example:

HTML:

<body ng-app="app">
  <div ng-controller="ctrl">
    <dir model="foo.bar"></dir>
    Outside directive: {{foo.bar}}
  </div>
</body>

JS:

var app = angular.module('app',[])
  .controller('ctrl', function($scope){
    $scope.foo = { bar: 'baz' };
  })
  .directive('dir', function(){
    return {
      restrict: 'E',
      scope: {
        model: '='
      },
      template: '<div ng-if="true"><input type="text" ng-model="model" /><br/></div>'
    }
  });

The desired behaviour here is that the input's value is bound to the outer scope's foo.bar property, via the the directive's (isolate) scope model property. That doesn't happen, because the ng-if directive on the template's enclosing div creates a new scope, so it's that scope's model that gets updated, not the directive's scope's. Ordinarily you solve these ng-model issues by making sure there's a dot in the expression, but I can't see any way to do that here. I wondered if I might be able to use something like this for my directive:

{
  restrict: 'E',
  scope: {
    model: {
      value: '=model'
    }
  },
  template: '<div ng-if="true"><input type="text" ng-model="model.value" /><br/></div>'
}

but that doesn't work...

Plunker


回答1:


You are right - ng-if creates a child scope which is causing a problem when text is entered in the input text field. It creates a shadow property named 'model' in child scope which is a copy of the parent scope variable with the same name - effectively breaking the two-way model binding.

The fix for this is simple. In your template, specify the $parent prefix:

  template: '<div ng-if="true">
                   <input type="text" ng-model="$parent.model" /><br/>
             </div>'

This ensures that it will resolve 'model' from the $parent scope, which you've already setup for two-way model binding through the isolated scope.

In the end, the '.' in ng-model saves the day. I find it useful to think about anything left of the dot as a way for Angular to resolve the property through scope inheritance. Without the dot, resolving the property only becomes an issue when we're assigning scope variables (otherwise, lookups are fine, including read-only {{model}} binding expressions).




回答2:


ng-if creates an additional prototypally inheriting scope, so ng-model="model" binds to the inherited property of the new scope and not to the 2-way binded property of the directive scope.

Change it to ng-show and it will work.

You can use a small Firebug extension i've written to inspect angular scopes.



来源:https://stackoverflow.com/questions/24265842/angular-directive-using-ng-model-within-isolate-scope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!