1

I have an issue while developing my Angular library : angular-coq.

I'm trying to provide these features :

<div ng-controller="myController">
    <form coq-model="team1">
        <!-- Inputs will be automatically added to form (wrapped in <p>) -->
    </form>
</div>

With myController that expose in scope team1, a custom class with 2 attributes : id, name.

The CoqModel directive will append to element a <input coq-model-attribute="..."> for each attribute.

CoqModelAttribute directive need a CoqModel as parent to have reference of the current model (here team1) and will compile as follow:

<div ng-controller="myController">
    <form coq-model="team1">
        <input type="<attribute_name>" ng-model="team1.<attribute_name>" coq-model-attribute="<attribute_name>"/>
    </form>
</div>

Here is the implementation of CoqModel directive and here is the implementation of CoqModelAttribute directive ( too large to paste here )

You will see that I "double-$compile" CoqModel directive. If I don't do this, the generated inputs ng-model will not be binded..

So everything works fine expect that the "double-$compile" cause some issues with ng-click.

In this case :

<div ng-controller="myController">
    <form coq-model="team1">
        <input coq-model-attribute="name"/>
        <br />
        <input type="button" value="click me" ng-click="team1.update()" />
    </form>
</div>

Clicking on "click me" will call the method team1.update 2 times..

I've tried a lot of different refactoring, all failed to solve this issue... If one of you is an angular expert, please show me how to fix this :)

Thanks a lot !

Charly Poly
  • 384
  • 1
  • 8
  • 1
    What are you doing that you need to manually call `$compile` in the first place? It looks like most of the logic in your pre `link` function generates markup which shouldn't be done here. You should be using a template for your directive and using that for creating your markup. Even if you really need to generate markup, it should be done inside of your directive's `compile` function, not `link`. Check out this explanation of ngRepeat for example: http://liamkaufman.com/blog/2013/05/13/understanding-angularjs-directives-part1-ng-repeat-and-compile/ – Justin Niessner Jun 13 '14 at 15:45
  • Hi @ju Thanks for your fast reply. I cannot generate the markup in the compile function cause I need to $parse attributes value to know how many nodes to create. And $parse need scope to evaluate values... You see the problem ? – Charly Poly Jun 16 '14 at 20:31

1 Answers1

0

Here is a link to a similar issue on Stack Overflow, the important bit being:

When you put your directive on the same element with ng-repeat and call $compile(element)(scope);, your element is recompiled including the ng-repeat, causing the ng-repeat to run one more time.

Perhaps during the second $compile, your button element is recompiled including the ng-click, causing the ng-click to run twice.

This hard-coded solution might work. Fill in the (selectorForYourButton) with a selector for the problem button and include this snippit right above the second $compile.

(selectorForYourButton).removeAttr("ng-click");

This may just remove the functionality of the ng-click altogether, though! If so, add the ng-click attribute back after the second $compile.

Or perhaps try replacing your priority:101 in coqModelAttribute directive with

  priority:1500,
  terminal:true,

to avoid compiling again after angular has compiled the element.

Community
  • 1
  • 1
  • Thanks for your reply ! The first solution seems to me to be a hack and I'm searching for a real solution for my Angular problem. The second one, more logical still not explain why do I need to double-compile my generated markup. I think that I'm missing something in the compile/link directive mechanism... I keep your second solution for know as a fix but I'm still searching a strong implementation for my `coq-model` directive – Charly Poly Jun 16 '14 at 20:35