AngularJS custom directive within ng-repeat with dynamic attributes and two way binding

天涯浪子 提交于 2020-01-25 04:46:28

问题


I'm banging my head on the wall over this for days and finally decided to post this question since I can't find an answer that matches what I'm trying to do.

Context: I'm building a dynamic form building platform that describes form elements in a JSON structure like this -

    {
        "name": "email",
        "type": "email",
        "text": "Your Email",
        "model": "user.profile.email"
    } 

And then in the View I have a recursive ng-repeat that includes the field template like this -

<script type="text/ng-template" id="field.html">
    <div ng-if="field.type === 'email'" class="{{field.class}}">
        <p translate="{{field.text}}"></p>
        <input type="{{field.type}}" name="{{field.name}}" class="form-control" dyn-model="{{field.model}}">
    </div>
</script>

As you see, I use a custom directive dynModel to create the ng-model attribute with interpolated value of the model from the string value. So far do good.

Now I have a more complex scenario in which I have a collection of fields that can be added or removed by clicking on Add button or removeMe button. See below -

         {
            "name": "urls",
            "type": "collection",
            "text": "Your Profile URLs",
            "model": "user.profile.urls",
            "items": [
                {
                    "name": "url",
                    "type": "url",
                    "text": "Facebook URL",
                    "model": "url"
                },
                {
                    "name": "url",
                    "type": "url",
                    "text": "Facebook URL",
                    "model": "url"
                }
            ],
            "action_button": {
                "name": "add",
                "type": "action",
                "action": "addURL"
            }
      }

 <div ng-if="field.type === 'collection'">
    <button class="btn btn-info"  dyn-click click-action="{{field.action_button.action}}" click-model="{{field.model}}">{{field.action_button.text}}</button>
     <div dyn-ng-repeat="item in {{field.model}}" >
        <div ng-repeat="field in field.items" ng-include src="'field.html'"></div>
     </div>
</div>

As you'll notice, I have another custom directive that takes care of interpolation of {{field.model}} from the previous ng-repeat (not shown).

Now to the crux of the issue. As you see in the template, I have nested ng-repeats, the first one iterates through user.profile.urls and the second one iterates through the field parameters in JSON and creates the HTML tags, etc. One of those fields is a button (action_button) that is used to add more URLS to the list. When I click the button, I want it to trigger a function in my controller and effectively add a new child to the parent model (user.profile.urls). I then also want each URL, existing and new to have a remove button next to them that will be dynamic and will remove that particular item from the model.

If you see the code above, I have a custom directive dyn-click that reads in the

click-action="{{field.action_button.action}}" 

That contains the function name (addURL) to be called that resides in my controller and the model

click-model="{{field.model}}"

(user.profile.urls) to which the new item is to be added. This is not working. The reason for this complexity is that I have multiple levels of nesting and at each level there are dynamic elements that need to be interpolated and bound. The directive dyn-click looks like this right now -

exports = module.exports = function (ngModule) {
    ngModule.directive("dynClick",function() {
        return {
            restrict: 'A',  
            link: function(scope,element,attrs) {
                $(element).click(function(e, rowid){
                    scope.clickAction(scope.clickModel, scope.$index);
                });
            }
        };
    });
};

With this code, when I click on the rendered form's Add button, the code in the $(element).click method above gets executed giving the following error -

Uncaught TypeError: undefined is not a function

I have tried a few different things with scope:{} in the dyn-click directive, with different errors and none of them have worked completely with two way binding of the model and calling the function as expected.

Help!

EDIT-1 - please see the comments:

        $(element).click(function(e, rowid){
            scope.$eval(attrs["clickAction"])(scope.$eval(attrs["clickModel"]), scope.$index);
        });

EDIT-2: The plunker is here - http://plnkr.co/edit/DoacjRnO61g4IYodPwWu?p=preview. Still tweaking it to get it right, but you guys should be able to see the necessary pieces. Thanks!

EDIT-3: Thanks Sebastian. The new plunker is here - http://plnkr.co/edit/Z6ViT7scubMxa17SFgtx?p=preview . The issue with the field.items ng-repeat still exists. For some reason the inner ng-repeat is not being executed. Any ideas? Josep, Sebastian?

来源:https://stackoverflow.com/questions/26683946/angularjs-custom-directive-within-ng-repeat-with-dynamic-attributes-and-two-way

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