Decorating directives with other directives

138 просмотров
Перейти к первому непрочитанному сообщению

Will Jones

не прочитано,
29 нояб. 2013 г., 09:12:4429.11.2013
– ang...@googlegroups.com
Hi all,

I'm wondering if there an analogue of the decorator pattern in Angular with respect to directives. I know that I can decorate services as they are requested from the injector, but I'd like something simpler: given a directive, I want to wrap it in another directive which exposes the same interface whilst adding additional behaviour. Please see http://plnkr.co/edit/annFYbVcajpQ5tGjJHHN?p=info for a working example of what I mean, what and how I've currently achieved it (which is a bit of a hack).

My questions are: is this possible? Is this against "the AngularJS way" of thinking? I appreciate that I can search up a directive hierarchy to find controllers and interact that way, but can I search downwards too?

Thanks in advance for any help,
Will

Martin Lemanski

не прочитано,
29 нояб. 2013 г., 10:22:3729.11.2013
– ang...@googlegroups.com
I don't know if you meant something like this?
 
 
I changed your plunkr a bit.
 
You just need to pass the value you want to read from to both directives and if you want something to be passed out, you do it the same way (through the scope).
I have to say, I don't know if this is the recomended way. But still, the new script is easier to read and understand then the previous script.
 
Cheers, Martin

Daniel Tabuenca

не прочитано,
29 нояб. 2013 г., 13:10:2829.11.2013
– ang...@googlegroups.com

There are many ways to wrap, combine, augment and re-use directives. But the best way depends on your actual use-case and what you are trying to accomplish. In your case, I would argue wrapping an element within-element is not the most semantic way of doing it.

I created a new example based on yours that just focuses on decorating the my-form directive by appending a submit button on the end:

http://plnkr.co/edit/SFIPXwLnozSY6fLOOOyU?p=preview

The syntax for using this “decorator” would be:

<my-form with-submit-button values="values.form"></my-form>

This is more semantically correct than if you were to do the same “decorator” by wrapping:

<with-submit-button>
    <my-form values="values.form"></myForm>
</with-submit-button>

Here is the code for the ‘with-submit-button’ directive:

module.directive('withSubmitButton', ['$compile', function($compile) {
  return {
    restrict: 'A',
    compile: function() {
      var submitButton = $compile('<button ng-click="submit()">Submit</button>');
      return function link(scope, element) {
        submitButton(scope, function(dom){
            element.append(dom);  
        })

        scope.submit = function() {
          console.log('Submitting ' + JSON.stringify(scope.values));
        };
      };  
    }
  };
}]);

Notice how you can’t use template: because only one directive is allowed to use template. Instead we inject $compile: and use it to compile are little button template, we then link this button to our scope and append it to our element.

This isn’t the only way to do this, but like I said, there is no “one way” and the best way will depend a lot on your actual use case.

Will Jones

не прочитано,
2 дек. 2013 г., 03:01:5002.12.2013
– ang...@googlegroups.com
Hi both,

Thanks for your responses. Perhaps it's worth pointing out that I'm building these directives using JavaScript code; for example, given some "interface", Viewable, say:

interface Viewable {
  public getTemplate();
}

where getTemplate() is expected to return some (Angular-compilable) snippet, I'm trying to write an instance MyDecorator that takes an existing instance of Viewable and wraps its implementation of getTemplate(). Hence my desire to do it with wrapping.

That said, I appreciate that perhaps this is a flaw in my design -- it may be that it does not make sense to apply the traditional decorator pattern here. I think I agree with Daniel's point that attributes are the "natural" decorators for element-based directives, so perhaps I'll adopt something in which getTemplate() is parameterised, or even returns a DOM element to which attributes can be added. 

Thanks again for taking the time to reply,
Will
Ответить всем
Отправить сообщение автору
Переслать
0 новых сообщений