Hi,
I'm starting to write a project using Angular and Ignite UI controls, especially the igGrid. So I got the angular directives and created a grid and set a data source which is working fine. Now I'm getting stuck on how I could trigger a function in my Angular controller from a template column. There is a sample on your page showing how to call a function by using the onclick event but this of course won't be executed within the controller so I would like to use something like the ng-click binding. As a sample what I already have here is the column definition:
<column key="Delete" header-text="Delete" data-type="string" unbound=true width="90px" template="{{getHtml('#deleteTemplate')}}"></column>
And this is the template I defined that is currently calling a javascript function getting passed the data
<script id="deleteTemplate" type="text/x-jquery-tmpl"><input type='button' onclick='alert("{{>#data}}")' value='Delete row' /></script>
As you can see I am using the jsrender engine for templates. Is there a way to use ng-click on this button and make it call a function on the angular controller of the context?
As a side question - I switched to jsrender because I could not find a solution to use an {{if}} within an {{each}} - is this possible with the Infragistics rendering engine?
The delete is just a sample – I know I could do this by using the Updating events but I have some other scenarios where I will need to call a function on the Controller and pass it the data of the row the button is shown in.
Any help would be appreciated.
This is something I've been wanting to try for a while as well and my basic solution was to bring in the '$compile' service into my controller and handle the dataRendered event on the grid to process angular directives in the markup:
app.controller('gridController', ['$scope', '$compile', 'northwind', function ($scope, $compile, northwind) { //... $scope.compileRows = function(evt, ui) { $compile(ui.owner.element)($scope); }; //... }]);
And you use the templating engine to give you the key to use with the ngClick call:
<script id="deleteTemplate" type="text/x-jquery-tmpl"> <input type='button' ng-click='deleteProductByKey({{>ProductID}})' value='Delete' /> </script> <ig-grid id="grid1" data-source="northwind" templating-engine="jsrender" event-data-rendered="compileRows" ...
Branch: https://github.com/damyanpetev/igniteui-angular/tree/angular-compiled-jsrender/samples
Sample: http://damyanpetev.github.io/igniteui-angular/samples/igGrid-compiled-jsrender.html
Reasoning: I've already described in one of the issues that $compile is not suitable for templating (as the grid is designed to build the DOM as sting for performance) and live linked nodes won't play well here. The $interpolate however is essentially equivalent to a templating function and can be used (check out the sample). Anything that requires live binding needs to happen after the templating and DOM creation are done, which is what I did. You will still need to be careful for conflicts between templating and angular syntax. And because the grid (and directives in theory) needs to be in control of/rely on its own markup to perform features, I suggest you thread carefully with compiling directives in the rows. At least for this simple sample there doesn't seem to be any impact that I saw.
In any case, we'd love to hear your feedback so you can always submit a Product Idea or visit the official repo in GitHub.
Thanks,
Damyan
Hello Damyan,
thanks for this input. I used the $compile as in the sample provided and it works. I don't quite understand the part about using $interpolate - you are saying I should look at the sample but that seems to be using $compile or am I looking in the wrong place? What exactly would using interpolate improve?
In your post you mentioned using $compile for rendering. Does this mean you suggest using Angular templates instead of jsRender templates? That sounds interesting - how would that work? I would prefer working with just Ignite UI and Angular instead of also having to use jsRender.
Another question I'm having is how I could combine templating/formatting with filters/sorting. I already have another post for this (https://ko.infragistics.com/community/forums/f/ignite-ui-for-javascript/93115/filtering-sorting-a-template-column-or-updating-a-formula-column) talking to Martin but maybe you can also give some insight into this as you seem to do a lot of work regarding templating. If there is no easy way to do that yet I will submit a Product Idea to allow filtering on values returned by a template/formatter but how would you suggest solving this for now?
Thanks for you help.
I noticed that if I add a row to the grid the data-rendered event is not triggered again. This means the function will not be called on the new row. How would you solve this?
Hi ruud7,
We are continuing to look into your questions. Since Damyan is more familiar with the scenario here, he can better answer your questions.
We will have another update for you by Tuesday.
Please see my responses to your questions below.
Q: I don't quite understand the part about using $interpolate - you are saying I should look at the sample but that seems to be using $compile or am I looking in the wrong place?
A: Damyan may have provided the wrong link here. I found the following of his Github pages which uses the $interpolateService for the templating.
https://github.com/damyanpetev/igniteui-angular/blob/angular-templating/samples/igGrid-interpolate.html
Q: What exactly would using interpolate improve?
A: As far as what $interpolate offers over $compile, I am not sure of Damyan's research into this, but $compile uses $interpolate. Using $interpolate instead cuts out any extra overhead of using $compile while accomplishing the core functionality needed.
Q: I noticed that if I add a row to the grid the data-rendered event is not triggered again. This means the function will not be called on the new row. How would you solve this?
A: I am assuming you are using the $compile method Damyan mentioned here. Using $interpolate also prevents the issue where data-rendered event is not fired, since you do not need to use the data-rendered event. The templating engine automatically takes the $interpolate template into consideration when adding a new row.
Q: In your post you mentioned using $compile for rendering. Does this mean you suggest using Angular templates instead of jsRender templates? That sounds interesting - how would that work?
A: I have slightly modified Damyan's sample and attached it to this post. This demonstrates using the $interpolate method and using it for the templating by overriding $.ig.tmpl.
If you have any further questions or concerns with this, please let us know.
Hello ruud7,
Please let me know if you need further assistance with this issue.
Hello Michael,
thanks for your replies. I tried out your sample and had some problems of it running very slow. The Northwind data seems to have been the reason, so I exchanged that. Afterwards it was running smooth but I had trouble getting an ng-click to work. I added an ng-click calling a message on the Controller scope but it does not get called. What would I need to do to get that working. Also it seems to me the ng-class in your sample doesn't work and it just takes the class={{style}}. Does the interpolate even handle the ng-... attributes?
Thanks for your support.
I'm developing an angularJS app using Infragistics Ignite UI controls. I'm using the iggrid control to display a few information in a page.
I should be able to select a few records and then click on a 'Process' button which will call a method in the Angular controller. I would like to know in the controller that what records are selected in the iggrid.
I've pasted the code snippet below. Can you please suggest the best way to accomplish this ?
<
<ig-grid id="grid" height="850px"
data-source="c.reprocessingData">
<columns>
<column key="isSelected" header-text="Select" template="<input type='checkbox' ng-model='${isSelected}'>" data-type="bool"></column>
.
</columns>
<features>
<feature name="Paging" page-size="20">
</feature>
<feature name="Filtering">
<feature name="Sorting">
</features>
</ig-grid>
<div class="divMargin setItemToBottom" style="height:10%;">
<button type="button" ng-click="c.process()" class="btn btn-default">process</button>
</div>
isSelected is a valid property in the "reprocessingdata" collection. I'm expecting the template to set this property on the checkbox select, so that I can access the selected items in the controller on process button click.
Please let me know if you need further assistance with this.
In order to use any Angular directives in the template, you will need to use $compile rather than $interpolate. This also explains why ng-class doesn't work in my sample. $interpolate understands the "{{style}}" syntax and places the $scope.style value into it. (which is set when $scopeRef.calculateStyle(); is called)
The following StackOverflow questions provide some useful information on this:
http://stackoverflow.com/questions/20911214/geting-ng-repeat-to-work-inside-of-angularjss-interpolate-service
http://stackoverflow.com/questions/17900588/what-is-the-difference-between-the-parse-interpolate-and-compile-services