stop execution of other directive on my custom element directive

Deadly 提交于 2019-12-24 16:46:03

问题


i have a custom element directive e.g. like below

  <my-wrapper ng-model="values.abc" unique-check="" list="list" prop="name"> </my-wrapper>

This directive does require ng-model which is later being set on the inner input tag

  <input type="text" name="myfield" ng-model="'+attrs.ngModel+'"/>

the problem happening is when I check console I can see ng-model on directive is not same as ng-model on input tag.

How can I make sure that the ng-model on outer tag is not created and its created only once inside my directive.

my directive code is below

app.directive("myWrapper", function(){

  var templateFn = function(element, attrs){
    return '<div ng-form="myform">'+
          '<input type="text" name="myfield" ng-model="'+attrs.ngModel+'"/>'+
          '<span>(inside directive) : isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>'
          '</div>';
  }

  return {
    restrict :'E',
    template : templateFn,
    require: 'ngModel',
    scope: true
  }
});

Please note that above is just a shortened version of my directive, and I have keep scope: true because of requirement in the overall scenario.

If its not clear what I am talking about, please checkout the console of THIS PLUNKER

I tried solutions with terminal : true and/or priority : 1001 so that the ng-model is not created on the directive html but only on input tag, but none of them worked.

yes, one solution can be to replace ng-model with lets say my-model on the directive and then again add it as ng-model on input tag, but then its being used at almost 1000s of places in my app, so really wont like to replace it as such.

any other way to solve this problem.


回答1:


So try this plunker. Basically I made the my-wrapper directive pass through its simple properties onto its input tag. For attributes that needed to be parsed, I simply parsed them and injected them into the scope create by the my-wrapper directive.

I am not very sure why you have a directive that wraps a form around a single input, but like you said this is a contrived example. Personally I would change this structure, but I tried not to be too disruptive.

Hope this helps. Maybe you can explain your intent behind this.




回答2:


You could try using transclusion. Instead of trying to do the hard part of breaking through standard AngularJS compilation, you could just change your structure to something like:

<my-wrapper>
    <input name="..." ng-model="...">
</my-wrapper>

and make your directive expand the wrapper into your template with transcluded input inside it. (See the transclude option in $compile documentation.) This would increase readability of your templates as well.


Alternatively, if you need your directive to generate complex content (multiple inputs, etc.) all encapsulated and bound to that single ng-model, you could leave the ng-model where it is and make your directive completely encapsulated. By this I mean something like:

.directive('myComplexField', function () {
    return {
        scope: {},
        require: 'ngModel',
        link: function ($scope, $element, $attrs, ngModelCtrl) {
            ngModelCtrl.$formatters.push(function (modelValue) {
                // ... (update your isolated model based on external model change)
            });
            ngModelCtrl.$parsers.push(function (viewValue) {
                // ... (update external model based on your isolated model)
            });
            $scope.$watch('... (properties of your isolated model)', function () {
                // force sync (parser code above will take care of setting the real value)
                ngModelCtrl.$setViewValue(!ngModelCtrl.$viewValue);
            });
        }
    };
})

(see ngModelController documentation). You just need to be careful not to create an infinite loop between your $parser and $formatter.


If you're really dead set on leaving ng-model on your wrapper and skipping it using priority and terminal, it's pretty simple:

.directive('foo', function ($compile, $timeout) {
    return {
        restrict: 'E',
        priority: 2,  // ngModel priority is 1 (see the docs)
        terminal: true,
        link: function ($scope, $element) {
            $compile($element, undefined, 1)($scope);  // compiles priority *lower than 1*
        }
    };
}

This approach should be avoided if at all possible, because it has many apparent downsides and no real upside.



来源:https://stackoverflow.com/questions/27559982/stop-execution-of-other-directive-on-my-custom-element-directive

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