问题
I have created a dropdown list like feature using angualrjs directive, The directive is working somewhat but not in correct way I expected.
Following are the issues which I am facing.
- The drop-down list alignment is correct for static but not for dynamic
- I am not able to select any of the option list since
getValue
function which I have defined in the parent directive is not been invoked from the trancluded directive
Can anyone please tell me some solution for this
My code is as given below
PLUNKER
<div ng-controller="MainCtrl">
Static
<grant-parent ng-model="grand1">
<parent label="Parent1" value="12">
<child value="56" label="Child1">Child1</child>
<child value="57" label="Child2">Child2</child>
</parent>
<parent label="Parent1" value="13">
<child value="58" label="Child3">Child3</child>
<child value="59" label="Child4">Child4</child>
</parent>
</grant-parent>
Dynamic
<grant-parent ng-model="grand2">
<parent ng-repeat="parent in data" label="{{parent.parentName}}" value="{{parent.parentId}}">
<child ng-repeat="child in parent.childrens" label="{{child.name}}" value="{{child.id}}">{{child.name}}</child>
</parent>
</grant-parent>
</div>
回答1:
Transclusion and ng-repeat
have caused me headaches, and I thought it would be challenging, but the solution proves quite simple:
Remove the DOM manipulation from your link function and do the transclusion in the template!
I.e. <div ng-transclude></div>
in the template of the parent
and remove this line: elm.find('div').replaceWith(transclude())
.
Forked plunk: http://plnkr.co/edit/UGp6D29yxnu0uJwD1BM2?p=preview
Now the markup comes out a bit different, the wrapper <div>
still exists. Although there seems to be no visual difference, this may not be what you want. I do not think there is a sane way to get around this, so I would suggest altering the layout a bit: Why don't you place the children inside the parent <li>
, e.g. as:
<li>
<b><a href='#' ng-click='getValue(optGroupLabel,optGroupValue)'>{{optGroupLabel}}<span class='value'>{{optGroupValue}}</span></a></b>
<div ng-transclude></div><!-- the div is now inside the li -->
</li>
This works in the plunker, but the markup is still invalid (<li>
within <div>
).
The best solution is to wrap the children in their own <ul>
, i.e.:
<li>
<b><a href='#' ng-click='getValue(optGroupLabel,optGroupValue)'>{{optGroupLabel}}<span class='value'>{{optGroupValue}}</span></a></b>
<ul ng-transclude></ul><!-- The div is replaced with ul -->
</li>
This does not work in the plunk as it is, but should work with a little CSS tweaking.
Concerning getValue
You have gotten wrong how isolated scopes and transclusion work. The grandParent
directive defines the getValue
method in its isolated scope. The transcluded things (the parent
and child
directives) get the outer scope, i.e. the scope of the MainCtrl
. A solution is to move getValue()
to the MainCtrl
.
A better solution would be to pass a callback to the descendants of the grandparent, e.g. as scope: { assignValue: '&' }
. But this solution cannot be implemented for the code in its current form because the grandparent does not directly include its children, so it cannot pass arguments to them.
The final solution - copied from the comments: move getValue
to the controller of grandParent, have the parent and children require the grandparent and call that function. See http://plnkr.co/edit/pS9SspLaoPlqoWMYr8I0?p=preview
来源:https://stackoverflow.com/questions/29426932/angularjs-function-in-parent-directive-not-getting-called-from-transcluded-html