Why can't I bind input type "checkbox" in cellTemplate? - angular-ui-grid

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><img class="icon" alt=""/></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.

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.

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.

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

Related

Angular ui grid disable sorting after cell edit

For display tabular data , I am using angular ui-grid
if a column is sorted and then if we edit the cell, the sorting gets kicked in and moves the row. I would like to disable sorting on cell edit, is there any way to do this?
Plnkr http://plnkr.co/edit/17H5K6nOEz9gf4Keeap9?p=preview
<div id="grid1" ui-grid="gridOptions" class="grid" ui-grid-edit >
</div>
var app = angular.module('app', ['ngAnimate', 'ngTouch', 'ui.grid','ui.grid.edit',
'ui.grid.selection',
'ui.grid.rowEdit', 'ui.grid.cellNav']);
app.controller('MainCtrl', function($scope) {
$scope.gridOptions = {
enableSorting: true,
columnDefs: [
{ field: 'A' },
{ field: 'B' },
{ field: 'C', enableSorting: false }
],
onRegisterApi: function( gridApi ) {
$scope.gridApi = gridApi;
}
};
$scope.gridOptions.data = [{'A':'a1', 'B':'b1', 'C':'c1'}, {'A':'a3', 'B':'b3', 'C':'c3'}, {'A':'a2', 'B':'b2', 'C':'c2'}];
});

Formly bootstrap. How do I show label with html?

I am using angularjs formly. Bootstrap template. I am looking a way to show html code I label. Now they are escaped when display
Here is the formly fields
vm.fields = [
{
key: 'awesome',
type: 'checkbox',
templateOptions: { label: 'this is a test' }
},
{
key: 'exampleDirective',
template: '<div example-directive></div>',
templateOptions: {
label: 'Example Directive',
}
}
];
I expected the A tag in "this is a test" can render properly.
In my case in with a textarea but i hope this help you to made a similar formly type with checkbox that can use html in label
I create a new type caled textareaHtml, it just extend 'textarea' and use this wrapper 'labelHtml' that load html with
'<span ng-bind-html="to.label" ></span>',
here the code
app.run(function(formlyConfig ) {
formlyConfig.setWrapper(
{
name: 'labelHtml',
template: [
'<div>',
'<label for="{{id}}" class="control-label {{to.labelSrOnly ? \'sr-only\' : \'\'}}" ng-if="to.label">',
'<span ng-bind-html="to.label" ></span>',
'{{to.required ? \'*\' : \'\'}}',
'</label>',
'<formly-transclude></formly-transclude>',
'</div>'
].join(' ')
}
);
formlyConfig.setType({
name: 'textareaHtml',
extends: 'textarea',
wrapper: ['labelHtml', 'bootstrapHasError']
});
});
I fixed the #imaginabit answer:
<script type="text/ng-template" id="checkboximp.html">
<div class="checkbox">
<label>
<input type="checkbox"
class="formly-field-checkbox"
ng-model="model[options.key]">
{{to.required ? '*' : ''}}
<div ng-bind-html="to.label"> </div>
</label>
</div>
</script>
/* global angular */
(function() {
'use strict';
var app = angular.module('formlyExample', ['formly', 'formlyBootstrap', 'ngSanitize'], function config(formlyConfigProvider) {
// set templates here
formlyConfigProvider.setType({
name: 'checkboxHtml',
extends: 'checkbox',
templateUrl: 'checkboximp.html',
wrapper: ['bootstrapHasError']
});
});
app.controller('MainCtrl', function MainCtrl(formlyVersion) {
var vm = this;
// funcation assignment
vm.onSubmit = onSubmit;
// variable assignment
vm.author = { // optionally fill in your info below :-)
name: 'Kent C. Dodds',
url: 'https://twitter.com/kentcdodds' // a link to your twitter/github/blog/whatever
};
vm.exampleTitle = 'Introduction';
vm.env = {
angularVersion: angular.version.full,
formlyVersion: formlyVersion
};
vm.model = {
awesome: true
};
vm.options = {
formState: {
awesomeIsForced: false
}
};
vm.fields = [
{
key: 'awesome',
type: 'checkbox',
templateOptions: { label: 'this is a test' }
},
{
key: 'awesome2',
type: 'checkboxHtml',
templateOptions: { label: 'this is a from j. lennon' }
}
];
// function definition
function onSubmit() {
alert(JSON.stringify(vm.model), null, 2);
}
});
})();
http://jsbin.com/dunuyakiwe/2/edit?html,js,output
Just two observations:
It's necessary to have angular sanitize library, and that would make the template work fine (ng-bind-html directive).
The default checkbox formly template has an embedded label in the component, so is not possible to use that out of the box, that's why it's simpler to create our own type.

How to insert a dropdownlist in the header of a kendo ui grid to adjust its column value

I am trying to insert a dropdownlist on the title of a kendo ui grid. Essentially I am following this sample: http://dojo.telerik.com/#rkonstantinov/afOxa
The following is my code.
<div id="grid"></div>
<script type="text/x-kendo-template" id="myFileCount">
<input type="search" id="fileCountValue" style="width: 150px"/>
</script>
$("#grid").kendoGrid({
dataSource: dataSource,
columns: [
{
hidden: true,
field: "ID",
},
{
field: "FileCount",
title: "FileCount",
headerTemplate: kendo.template($("#myFileCount").html()),
width: 50,
sortable: false
},
],
editable: true
});
var gridA = $("#grid").data("kendoGrid");
gridA.find("#fileCountValue").kendoDropDownList({ //this line throws error
autoBind: false,
optionLabel: "All",
dataSource: [
{ Name: "1", Id: 1 },
{ Name: "2", Id: 2 }
],
dataTextField: "Name",
dataValueField: "Id",
change:function() {
var val = this.value();
for (var i = 0; i < dataSource.data().length; i++) {
dataSource.data()[i].Originals = val;
}
dataSource.data()[i].Originals = val;
grid.setDataSource(dataSource);
}
});
However, I am getting this error: 0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'find'. I have also indicated the line which throws this error in my code.
Thanks

give default value to md-autocomplete

How to pass default value in md-autocomplete?
Image 1 : HTML code
Image 2 : JS code
Image 3 : Output
As you can see, I am not getting any default country as output. Is there any way to do that?
Assign yr SearchText the default value & selectedItem the object.
$scope.local ={
...
searchText : 'Default Value',
selectedItem : 'Default object'
...
}
I write small codepen with autocomplete and default value.
What you must do:
Init main model.
Define model field, used in autocomplete md-selected-item property.
Define callback for loading autocomplete items.
Before save main model extract id (or other field) from associated field.
Main error in your code here:
$scope.local = {
...
selectedItem: 1, // Must be object, but not integer
...
}
(function(A) {
"use strict";
var app = A.module('app', ['ngMaterial']);
function main(
$q,
$scope,
$timeout
) {
$timeout(function() {
$scope.user = {
firstname: "Maxim",
lastname: "Dunaevsky",
group: {
id: 1,
title: "Administrator"
}
};
}, 500);
$scope.loadGroups = function(filterText) {
var d = $q.defer(),
allItems = [{
id: 1,
title: 'Administrator'
}, {
id: 2,
title: 'Manager'
}, {
id: 3,
title: 'Moderator'
}, {
id: 4,
title: 'VIP-User'
}, {
id: 5,
title: 'Standard user'
}];
$timeout(function() {
var items = [];
A.forEach(allItems, function(item) {
if (item.title.indexOf(filterText) > -1) {
items.push(item);
}
});
d.resolve(items);
}, 1000);
return d.promise;
};
}
main.$inject = [
'$q',
'$scope',
'$timeout'
];
app.controller('Main', main);
}(this.angular));
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/0.11.0/angular-material.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular-aria.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular-animate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/0.11.0/angular-material.min.js"></script>
</head>
<body ng-app="app" flex layout="column" layout-margin ng-controller="Main">
<md-content layout="column" class="md-whiteframe-z1" layout-margin>
<md-toolbar>
<div class="md-toolbar-tools">
<h3>Form</h3>
</div>
</md-toolbar>
<md-content class="md-whiteframe-z1">
<div class="md-padding">
<md-input-container>
<label for="firstname">First name</label>
<input type="text" name="firstname" ng-model="user.firstname" />
</md-input-container>
<md-input-container>
<label for="lastname">Last name</label>
<input type="text" name="lastname" ng-model="user.lastname" />
</md-input-container>
<md-autocomplete md-selected-item="user.group" md-items="item in loadGroups(filterText)" md-item-text="item.title" md-search-text="filterText">
<md-item-template>{{ item.title }}</md-item-template>
<md-not-found>No items.</md-not-found>
</md-autocomplete>
</div>
</md-content>
</md-content>
<md-content class="md-whiteframe-z1" layout-margin>
<md-toolbar>
<div class="md-toolbar-tools">
<h3>Model as JSON</h3>
</div>
</md-toolbar>
<md-content class="md-padding">
<p>
{{ user | json }}
</p>
</md-content>
</md-content>
</body>
I know this is an old question, but some people may benefit from my solution. I struggled with the problem of the model for the auto-complete being asynchronous and having my autocompletes as part of an ng-repeat. Many of the solutions to this problem found on the web have only a single auto complete and static data.
My solution was to add another directive to the autocomplete with a watch on the variable that I want to set as default for the auto complete.
in my template:
<md-autocomplete initscope='{{quote["Scope"+i]}}' ng-repeat='i in [1,2,3,4,5,6,7,8]'
class='m-1'
md-selected-item="ScopeSelected"
md-clear-button="true"
md-dropdown-position="top"
md-search-text="pScopeSearch"
md-selected-item-change='selectPScope(item.label,i)'
md-items="item in scopePSearch(pScopeSearch,i)"
md-item-text="item.label"
placeholder="Plowing Scope {{i}}"
md-min-length="3"
md-menu-class="autocomplete-custom-template"
>
then in my module:
Details.directive('initscope', function () {
return function (scope, element, attrs) {
scope.$watch(function (){
return attrs.initscope;
}, function (value, oldValue) {
//console.log(attrs.initscope)
if(oldValue=="" && value!="" && !scope.initialized){
//console.log(attrs.initscope);
var item = {id:0, order:0,label:attrs.initscope?attrs.initscope:"" }
scope.ScopeSelected = item;
scope.initialized = true;
}
});
};
});
this checks for changes to the quote["Scope"+i] (because initially it would be null) and creates an initial selected item and sets the autocompletes' selected item to that object. Then it sets an initialized value to true so that this never happens again.
I used timeout to do this.
$timeout(function() {
$scope.local = {selectedItem : 1}
}, 2000);

jQuery-JTable: add on click event for row?

I have to following code to show my user table, this is achieved by JTable.
<script type="text/javascript">
$(document).ready(function() {
$('#userTableContainer').jtable({
title: 'Users',
selecting: false,
paging: true,
pageSize: 15,
sorting: true,
addRecordButton: false,
saveUserPreferences: false,
create: false,
edit: false,
actions: {
listAction: 'user/getUsers.htm',
},
fields: {
username: {
title: 'username'
},
firstname: {
title: 'firstname'
},
lastname: {
title: 'lastname'
},
company: {
title: 'company'
}
}
});
$('#userTableContainer').jtable('load');
});
</script>
<div id="content">
<h1>Users</h1>
<br />
<div id="userTableContainer">
</div>
</div>
Is it possible to add a custom action event for every row?
So that i could submit a request like "user/showUser.htm" to my controller.
This should get you on your way:
$('#userTableContainer').jtable({
....
recordsLoaded: function(event, data) {
$('.jtable-data-row').click(function() {
var row_id = $(this).attr('data-record-key');
alert('clicked row with id '+row_id);
});
}
});

Resources