简体   繁体   中英

How to pass methods with pre defined argument to Angular JS Directives

I am trying to add an Action Buttons to my DataTable depending if the status is true by passing a method to the directive.

CONTROLLER.JS

_ctr.route = 'home.stocks';

_ctr.object = [
    {
        id: 1,
        name: 'XXXX',
        status: true
    }, {
        id: 2,
        name: 'XXXX',
        status: false
    }
];

_ctr.headers = {
    name: 'NAME',
    status: 'STATUS'
}

_ctr.method = row => {
    if (row.type) {
        return row['button'] = [
           {
               label: 'Edit',
               class: 'primary',
               state: _ctr.route + `.edit({ id : '${row.id}' })`
           }, {
               label: 'Delete',
               class: 'danger',
               state: _ctr.route + `.delete({ id : '${row.id}' })`
           }
        ];
    }
}

This is how I transfer variables to the Directive.

FORM.HTML

<template-table
     tb-object="{{ _ctr.object }}"
     tb-headers="{{ _ctr.headers }}"
     tb-method="{{ _ctr.method() }}">
</template-table>

This is my customized Table.

TEMPLATE.JS

app.directive('templateTable', function (factory, $compile) {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            tbMethod: '@',
            tbObject: '@',
            tbHeaders: '@',
        },
        link: (scope, element, attrs) => {
             attrs.$observe('tbObject', data => {
                 if (data) {
                     let object = scope.$eval(data);
                     let headers = scope.$eval(scope.tbHeaders);
                     let method = scope.tbMethod;
                     let headers_config = [];

                     // converting `headers` to DataTable Column Format
                     for (let prop in headers) {
                        headers_conf.push({ 
                             data: prop, 
                             bSortable: true, 
                             label: headers[prop] 
                        });
                      }

                      if (method) {
                          headers_conf.push({
                               mData: null,
                               bSortable: false,
                               label: 'ACTION',
                               mRender: function (row, type, full) {
                                    // calls method and passes `row` argument to method
                                    // checks if `row.type` is `true`
                                    row[method(row)];

                                    let button = row.button;
                                    let template = '';

                                    // if true appends 'Action Button'
                                    if (button) {
                                        button.map(res => {
                                         template += 
                                              `<a ui-sref="${res.state}" class="btn btn-${res.class} 
                                              mr-2" style="color: white;" role="button"> ${res.label} 
                                              </a>`;
                                        })
                                     }

                                 return `<td class="action-buttons"> ${template} </td>`;
                             }
                         });
                     }

                     scope.headers = headers_conf;

                     $("#listTable").DataTable({
                        data: object,
                        columns: headers_conf,
                        "fnDrawCallback": function (oSettings) {
                            $compile(angular.element($("#listTable")).contents()) 
                            (scope);
                        }
                    });
                 }
             });
        }
    }
});

This doesn't seem to work for me. What should I do to make the code above, work.

To pass a method to directive with isolate scope, don't use curly brackets:

<template-table
     tb-method="_ctr.method">
</template-table>

In the isolate scope directive, use one-way binding:

app.directive('templateTable', function (factory, $compile) {
    return {
        restrict: 'E',
        scope: {
            tbMethod: '<',
        },
        link: (scope, element, attrs) => {
            if (scope.tbMethod) {
               var row = "something";
               //Invoke method
               scope.tbMethod(row);
            };
        }
    }
})

From the Docs:

scope

The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the directive's element. These local properties are useful for aliasing values for templates. The keys in the object hash map to the name of the property on the isolate scope; the values define how the property is bound to the parent scope, via matching attributes on the directive's element: For more information, see

  • < or <attr - set up a one-way (one-directional) binding between a local scope property and an expression passed via the attribute attr. The expression is evaluated in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM