Why can't I bind input type "checkbox" in cellTemplate?
Asked Answered
P

3

7

Here is my plunker example: http://plnkr.co/edit/Tc9FRHAEoQlOqy7sk1Ae?p=preview

What I'm trying to do: Bind the checkbox html from field04 in my data to the cell using cellTemplate and still have access to its ng-click function.

Code in app.js:

var app = angular.module('app', ['ui.grid', 'ngSanitize']);

app.controller('MainCtrl', ['$scope', '$log', function ($scope, $log, $sce) {

$scope.myViewModel = {
  someProp:'abc',
  showMe : function(){
     alert(this.someProp);
  }
};

$scope.gridOptions = {
};

$scope.gridOptions.columnDefs = [
     { name: 'field01', field: 'field01' },
     { name: 'field02', field: 'field02'},
     { name: 'field03', field: 'field03', cellTemplate: '<input type="checkbox" ng-model="row.entity.field03" ng-click="$event.stopPropagation();getExternalScopes().showMe()">'},
     { name: 'field04', field: 'field04', cellTemplate: 'viewTemplate2'},
     { name: 'field05', field: 'field05', cellTemplate: 'viewTemplate2'} 
   ];

$scope.gridOptions.data = [
  {
      "field01": "one",
      "field02": "01",
      "field03": false,
      "field04": '',
      "field05": '',
  },
  {
      "field01": "two",
      "field02": "02",
      "field03": false,
      "field04": '',
      "field05": '',
  },
  {
      "field01": "three",
      "field02": "03",
      "field03": false,
      "field04": '<input type="checkbox" ng-model="row.entity.field03" ng-click="$event.stopPropagation();getExternalScopes().showMe()">',
      "field05": '<div><a href="#" title="icon link"><img class="icon" alt=""/></a></div>',
  }
];
$scope.toggle = function() {
  alert("toggled");
}
}]);

Code from index.html:

<body>

<div ng-controller="MainCtrl">
  <div ui-grid="gridOptions" external-scopes="myViewModel" class="grid"></div>
</div>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular-sanitize.min.js"></script>
<script src="app.js"></script>
<script type="text/ng-template" id="viewTemplate2">
  <span ng-bind-html="row.entity[col.field]"></span>
</script>

</body>

I am achieving the correct effect in field03 if I write the html in the columnDef. Thanks to TomMorgan's plunker here: http://plnkr.co/edit/9eRg9Yjl2ooeSuWMJ8x2?p=preview.

I can fill the cellTemplate with html from the data in field05.

Why is it not working for my checkbox in field04?

I'm new to angularjs and its difficult to separate "ui-grid" solutions from "ng-grid" solutions. I appreciate the help.

Produce answered 18/12, 2014 at 23:3 Comment(9)
Is there a reason you can't put your desired HTML in a cellTemplate within the columnDefs? Is it because the HTML you want is coming in as your data? The way you've achieved it for field03 would be the correct way of doing it. When working with ui-grid (which is ng-grid 3.0), you want to put your custom HTML in a cellTemplate.Chloroplast
When the data comes in I have to filter it somehow. For example, field03 is "permissions", if "permissions" : "canEdit" is true I need to display an edit icon. Also, the row item may have a document linked to it, if so I need to display a document link icon right next to the "canEdit" icon in field03. In "ui-grid" I can't figure out how to run scripts like that as the data gets loaded into the grid. I could do it in jqgrid using afterInsertRow: function(rowid, data){}Produce
You can build a custom filter in angular to handle that logic. You can then call that filter for that column as follows: { name: 'field04', field: 'field04', cellFilter: 'myNewFilter'}Chloroplast
I tried the cellFilter route first, however it does not handle html. Whatever gets returned from the filter is read as "text only", so my html gets printed out in the cell. CellFilter also does not work if you use cellTemplate.Produce
If you're using a cellTemplate, you can add the filter like this: cellTemplate: '<span>{{COL_FIELD | myFilter}}</span>'. Additionally, you can return HTML using a filter. Inject the $sce service into the filter and have the filter return this: return $sce.trustAsHtml("<span>custom html stuff </span>");Chloroplast
The filter is causing an infinitely accumulating "ReferenceError: $sce is not defined". I was referencing $sce in my grid controller, am I supposed to reference it somewhere else for the filter to work?Produce
You need to inject the $sce service into the new filter, not into your controller. Eg. app.filter('myNewFilter', function ($sce) {...Chloroplast
Injecting the $sce service into the new filter did get rid of the error, however the filter is still printing the html markup into the cell as text. I will link a separate plunker example for this problem when I can.Produce
Sorry for the delay. If you can produce a plunkr, I'm happy to walk you through it. The $sce service should allow you to return HTML to your view.Chloroplast
P
10

I am not sure if I understand your code.

You shouldn't put html code in your data. So I changed it to:

   $scope.gridOptions.data = [
      {
          "field01": "one",
          "field02": "01",
          "field03": false,
          "field04": '',
          "field05": '',
      },
      {
          "field01": "two",
          "field02": "02",
          "field03": false,
          "field04": '',
          "field05": '',
      },
      {
          "field01": "three",
          "field02": "03",
          "field03": false,
          "field04": '',
          "field05": '',
      }
    ];

Next: In your cell template pass a reference to the value that changes:

 { name: 'field03', field: 'field03', cellTemplate: '<input type="checkbox"
  ng-model="row.entity.field03" ng-click="$event.stopPropagation();
  getExternalScopes().showMe(row.entity.field03)">'}

Note that function showMe() now has a parameter:

showMe(row.entity.field03)

In the external scope you should react to the parameter:

$scope.myViewModel = {
  someProp:'abc',
  showMe : function(value){
     alert('toggled to: '+value);
  }
};

(You don't really need someProp)

The $scope.toggle() function can be removed, or can be called from showMe().

Furthermore, I added some debugging help to your html to show you that the binding works pretty well:

<div ng-controller="MainCtrl">
  <div ui-grid="gridOptions" external-scopes="myViewModel" class="grid"></div>
  <hr>
  {{gridOptions.data | json}}
</div>

Here is a Plunker. Is that what you want?

Update:

Here is another Plunker that has the checkbox in column 4.

Pilate answered 19/12, 2014 at 17:49 Comment(1)
Putting html in the data is something I do client side. When the data comes in I check each items "permissions" properties. For example, if "permissions" has "canEdit : true", "hasDocument : true" I need to display those corresponding icons in a single cell. The document icon needs to have a link associated with it to the actual file. In jqgrid I solved this by using an "afterInsertRow" function. But in ui-grid I do not know how to do the same thing. Should I post a new question regarding this? If I did it correctly I wouldn't have a checkbox cellTemplate problem?Produce
P
3

Here is a Plunker with appScope, external-scopes don't work anymore.

I've made some changes to work with new appScope:

 { name: 'field03', field: 'field03', cellTemplate: '<input type="checkbox"
  ng-model="row.entity.field03" ng-click="grid.appScope.showMe(row.entity.field03)">'}

In the scope you should react to the parameter but I've pulled from myViewModel and just created a function inside $scope:

$scope.showMe : function(value){
     alert('toggled to: '+value);
};

You can test code from version 15 against my version 16. My new version runs ok but 15 no.

Pragmatist answered 5/6, 2015 at 16:57 Comment(3)
Please include the relevant code bits in your answer.Bowse
I've never post here. It made some time to figure why my code wasn't go to the answer.Pragmatist
The plunkr's output is broken. Can't see table.Dreadfully
R
0

You need to use $sce to tell ng-bind-html that HTML content you are binding is safe.

I have forked your plunker and the solution for your question is http://plnkr.co/edit/JyTaF8niJlf9Wpb775kb?p=preview

    app.filter('unsafe', function ($sce) {
       return $sce.trustAsHtml;
    });

You have to use this filter with ng-bind-html

Rafaelarafaelia answered 12/1, 2017 at 6:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.