javascript - Angular Directive Template Update on Data Load -
i have directive data being received via api call. directive works fine, problem arises (i believe) because directive loaded before api call finishes. results in whole shebang not working. instead of expected output, {{user}}
.
my directive looks this:
app.directive('mydirective', function() { return { restrict: 'a', require: '^ngmodel', scope: { ngmodel: '=', }, template: '<tbody style="background-color: red;" ng-bind-html="renderhtml(listing_html)"></tbody>', controller: ['$scope', '$http', '$sce', function($scope, $http, $sce) { $scope.listing_html += "<td>{{user.name}}</td>" $scope.renderhtml = function(html_code) { return $sce.trustashtml(html_code); }; } ], link: function(scope, ielement, iattrs, ctrl) { scope.$watch('ngmodel', function(newval) { // *is* firing after data arrives, // {{user}} object populated. , `user in ngmodel` doesn't // run correctly either. console.log(scope.ngmodel); scope.listing_html = "<tr ng-repeat='user in ngmodel'><td>{{user}}</td></tr>" }) } }; });
and html simply
<table my-directive my-options='{"name": "name", "email": "email"}' ng-model='userdata'></table>
i've created plunker ton of comments explain issue.
this question very similar this one, key distinction of solution not working. adding ng-cloak
mine makes not display. may worth noting i've been using this reference on way construct directive.
i not 100% sure, believe ngbindhtml
not in case.
ngbindhtml
displaying "normal" html, want display angular, magic html.
need $compile
html angular-aware , link
compiled html scope.
i used following approach (with apparently results):
controller: function ($scope, $element, $compile) { var html = createtmpl(angular.fromjson($scope.myoptions)); $scope.$watch('ngmodel', function (newval) { var elem = angular.element(html); // creating element var linkingfn = $compile(elem); // compiling element linkingfn($scope); // linking element $element.html(''); // removing previous content $element.append(elem); // inserting new content // above purposedly explicit highlight // going on. it's moe concise equivalent be: //$element.html('').append($compile(html)($scope)); });
where createtmpl()
defined take account myoptions
, return appropriate template creating table header-row (based on keys of myoptions
) , data-rows properties defined myoptions
's values:
function createtmpl(options) { // construct header-row var html = '<tr>'; angular.foreach(options, function (value, key) { html += '<th>' + key + '</th>'; }); html += '</tr>\n'; // construct data-rows html += '<tr ng-repeat="user in ngmodel">'; angular.foreach(options, function (value, key) { html += '<td>{{user' + value + '}}</td>'; }); html += '</tr>\n'; // return template return html; }
see, also, short demo.
of course, demonstration purposes , not handle production-ready app should (e.g. accounting errors, missing properties, changes in myoptions
, whatnot).
update:
i had strong competion, did slight modification of code above in order support nested properties. e.g. given object following structure:
user = { name: 'expertsystem', company: { name: 'expertsystem s.a.', ranking: 100 } };
we can have company name displayed in column of our table, defining myoptions
this:
myoptions='{"company name": "company.name"}
Comments
Post a Comment