Angular UI Grid not updating directives in cells - angular-ui-grid

I have a ui grid that contains a directive, this directive has an isolated scope and changes it's template basing on some logic.
The problem is that, when sorting (and also when PAGING), the 'logic' of the directive seems to not be correctly "re-evaluated".
In the specific example, the rightmost column should only see some "11" while if you try to sort by id (or the other fields) you'll see some spurios '0' appearing.
this is the ui:
<div ng-app="myapp">
<div ng-controller="myctrl">
<div ui-grid="gridOptions" ng-style="gridStyle"></div>
</div>
</div>
this is the js:
var myapp = angular.module('myapp', ["ngRoute", "ui.grid"])
.controller('myctrl', function($scope) {
$scope.gridOptions = {
data: [{
id: 1,
name: "Max",
other: "pippo",
number: 1
}, {
id: 2,
name: "Adam",
other: "pluto",
number: 0
}, {
id: 3,
name: "Betty",
other: "paperino",
number: 0
}, {
id: 4,
name: "Sara",
other: "fava",
number: 1
}, {
id: 5,
name: "Favonio",
other: "favona",
number: 1
}],
columnDefs: [{
field: "id",
displayName: "ID"
}, {
field: "name",
displayName: "Name"
}, {
field: "other",
displayName: "Other"
}, {
field: "number",
cellTemplate: '<div class="ui-grid-cell-contents"><mydir data="row.entity"></mydir></div>'
}]
};
}).directive("mydir", function() {
return {
restrict: 'E',
scope: {
data: "=",
},
template: '<div><label ng-if="data.number==1">{{set}}</label></div>',
link: function(scope, iElement, iAttrs) {
scope.set = -1;
if (scope.data.number == 0) {
scope.set = 00;
} else {
scope.set = 11;
}
}
}
});
and here's a fiddle:
https://jsfiddle.net/27yrut4n/
Any hint?

In the end it's a known bug:
https://github.com/angular-ui/ui-grid/issues/4869
And I solved using watch like it's said here:
Directive rendered via UI-Grid cellTemplate rendering incorrectly

Related

How to validate select2?

I have a select2 as below:
<select class="form-select" id="ds" name="ds" tabindex="1" required></select>
I populate it using:
var data = [{ id: "0", text: "" }, { id: "1", text: "List" }, { id: "2", text: "Tags" }];
$('#ds').select2({
data: data
})
I try to validate it using below, but it's not working, what did I do wrong?
$form.each(function() {
var $this = $(this);
$this.validate({
rules: {
data_source: {
required: true
}
},
messages: {
data_source: {
required: 'Data source field is required'
}
}
});
});

How to prevent select2 to call select2:close the second time when selectOnClose is set to true?

I am using Select2 V. 4.0.10
I want to have a select2 that behaves the same way when you select using the Enter key and the Tab key.
What happens is that when selecting using the Tab key, the close event is called twice, which is not what was intended to do.
var data = [
{ id: 0, text: 'New' },
{ id: 1, text: 'In Process' },
{ id: 2, text: 'Draft' },
{ id: 3, text: 'Submitted' },
{ id: 4, text: 'Deleted' }
];
$(".test").select2({
allowClear: true,
selectOnClose: true,
data: data,
placeholder: "Select a status"
});
$("select.test", "body").off("select2:close").on("select2:close", function (e){
// This is called twice
console.log("select2:close");
});
select.test {
width: 200px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/select2.min.js"></script>
<select class="test"></select>
Here are the sequences of the select2 events that are triggered when selecting with the Tab/Enter key.
TAB
select2:opening
select2:open
select2:closing
select2:selecting
change
change.select
select2:closing
select2:close
select2:select
select2:close
ENTER
select2:opening
select2:open
select2:selecting
change
change.select
select2:closing
select2:close
select2:select
As the pattern in always the same, the solution was to create a variable that would be toggled on when select2:select was triggered, and use that to see if it was be used before.
Notice, instead of using the global window object you should rather use a class variable or a prototype property to store this boolean.
var data = [
{ id: 0, text: 'enhancement' },
{ id: 1, text: 'bug' },
{ id: 2, text: 'duplicate' },
{ id: 3, text: 'invalid' },
{ id: 4, text: 'wontfix' }
];
window._select2Select = false;
$(document).on('select2:select', "select", function (e) {
window._select2Select = true;
});
$(".test").select2({
allowClear: true,
selectOnClose: true,
data: data,
placeholder: "Select a status"
});
$("select.test", "body")
.off("select2:close")
.on("select2:close", function(e) {
if(window._select2Select){
window._select2Select = false;
return;
}
console.log("select2:close");
window._select2Select = false;
});

How do I remove an object from an array of objects. in knockoutJS. Error: Object doesn't support property or method 'remove'

How do I remove an object from an array of objects in Knockoutjs.
I am new to knockoutjs and any help will be appreciated.
A link to Jsfiddle
Line 24 in the HTML code on jsfiddle is the click binding to delete.
Line 67 in the javascript code on js fiddle is where the function to remove an object from the array is made.
I tried to use indexOf and splice Array functions on line 68 and 69 and it worked to remove but the DOM was not being updated.
Please take a look at the function removeProduct: function (product)
Html
<div>List of Product (<span data-bind="text: products().length"></span>)
</div>
<ul data-bind="foreach: products">
<li><span data-bind="text:name"></span>
Select
</li>
</ul>
<div>List of Group Ideas</div>
<ul data-bind="foreach: GroupIdeas">
<li data-bind="text:name">
<input type="button" value="Removethis" />
<input type="button" value="vote" />
</li>
</ul>
<div>List of Group members</div>
</body>
Javascript
$(function () {
var viewModel = {
productPrice: ko.observable(89),
productQty: ko.observable(2),
products: ko.observable([
{ name: "shoe", price: "788", id: 1 },
{ name: "blouse", price: "50", id: 2 },
{ name: "dress", price: "16", id: 3 },
{ name: "lipstick", price: "88", id: 4 },
{ name: "earring", price: "4", id: 5 },
{ name: "bra", price: "96", id: 6 },
{ name: "lingeringe", price: "48", id: 7 },
{ name: "neclace", price: "36", id: 8 },
]),
GroupIdeas: ko.observable([
{ name: "shoe", price: "788", prodId: 1, selectedby: "Akuba", memId:
1, votes: 3 },
{ name: "lingeringe", price: "48", prodId: 7, selectedby: "Isaac",
memId: 2, votes: 6 },
]),
GroupMember: ko.observable([
{ name: "Akuba", relation: "friend", id: 1 },
{ name: "Isaac", relation: "Husband", id: 2 },
{ name: "Ira", relation: "Sister", id: 3 },
{ name: "Davida", relation: "Mum", id: 4 }
]),
partyPerson: ko.observable("Ida"),
partyOrganiser: ko.observable("Royce"),
//addProduct = function () { /* ... leave unchanged ... */ }
removeProduct: function (product) {
/*var indexArr = viewModel.products().indexOf(product);
viewModel.products().splice(indexArr, 1)
*/
viewModel.products().remove(product)
console.log(product);
}
};
viewModel.totalAmt = ko.computed(function () {
return this.productPrice() * this.productQty();
}, viewModel);
ko.applyBindings(viewModel);
//ko.applyBindings(giftModel);
})**
Here's your updated fiddle.
You need to make products an observable array to take advantage of the remove function.
You need to make a reference to the viewmodel before you can refer to products, so your removeProduct function has to be written after the viewmodel initialisation. Similar to how you have written totalAmt.
viewModel.removeProduct = function (product) {
viewModel.products.remove(function(item){
return item.id === product.id;
});
}

filter the ui grid value based on the row check box is selected

This is the ui grid code( minimal)
//js file
vm.gridOptions1 = {
enableColumnResizing: true,
enableAutoResizing: false,
columnDefs: [
{
field: 'createdDate',
displayName: 'Created Date',
type: 'date',
cellFilter: 'date:"dd-MM-yyyy"',
enableHiding: false, headerTooltip: 'Created Date'
},{
name: 'Refer',
displayName: 'Refer', enableSorting: false, headerTooltip: 'Refer',
cellTemplate: '<input type="checkbox" ng-model="row.entity.isReferred" />'
}
]});
On click of this byutton I need to filter, get only rows which check box is selected(isReferred = true)
//html file
<button type="button" class="btn btn-primary-joli " ng-click="srchctrl.send">Send</button>
This is the file trying to get the filtered list based on the redeffered check box value, but its not working.
//JS file
vm.send = function () {
if (vm.gridApi.selection.data != null && vm.gridApi.selection.data != undefined) {
vm.referredList = filterFilter(vm.gridApi.selection.data, {
isReferred: true
});
console.log("referredList :"+JSON.stringify(referredList));
}
};
How can I get all the value ticked. I don't want to invoke method on each click event on check box.
I think the easiest way to achieve this is by using the gridApi.grid.registerRowsProcessor function. I have adapted a Plunker to show what I mean:
http://plnkr.co/edit/lyXcb90yQ0ErUJnSH7yF
Apps.js:
var app = angular.module('plunker', ['ui.grid']);
app.controller('MainCtrl', ['$scope', 'uiGridConstants', function($scope, uiGridConstants) {
$scope.gridOptions = {
columnDefs: [
{field: 'col1', displayName: 'Column 1', width: 175},
{field: 'col2', displayName: 'isReferred', width: '*'}
],
data: [
{ col1: "Hello 1",col2: true},
{ col1: "Hello 2", col2: false},
{ col1: "Hello 3", col2: true},
{ col1: "Hello 4", col2: false},
{ col1: "Hello 5", col2: true}
],
enableFiltering: true,
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
}
};
$scope.Filter = Filter;
$scope.ShowAll = ShowAll;
function ShowAll() {
$scope.gridApi.grid.removeRowsProcessor(myFilter);
$scope.gridApi.core.queueGridRefresh();
}
function Filter() {
$scope.gridApi.grid.registerRowsProcessor(myFilter, 150);
$scope.gridApi.core.queueGridRefresh();
}
function myFilter(renderableRows) {
renderableRows.forEach( function(row) {
row.visible = row.entity.col2;
});
return renderableRows;
}
}]);
Clicking the Filter button will register the myFilter RowsProcessor, which will iterate through all rows to alter the visible attribute.
Clicking the ShowAll button will remove the RowsProcessor, thus showing all previously hidden rows again.
Whenever an isReferred value changes, the filter will cause the grid to automatically update this change.

SELECT2 AJAX not selecting results - Ember.js Ember Cli Custom Component

The AJAX functionality of Select2 4.0.0 doesn't seem to be working. It displays the results from the AJAX however when you click on the a result item it does not select it. I have wasted hours on this any help would be appreciated.
The following code does not work:
var staticdata = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];
self._select = self.$().select2({
placeholder: self.get('placeholder'),
tokenSeparators: [','],
multiple: true,
ajax: {
url: "http://localhost:9990/api/v1/users/",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, page) {
return {
results: staticdata
};
},
cache: true
}
});
However when I try it WITHOUT Ajax it works and the results are selecting into the input field:
var staticdata = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];
self._select = self.$().select2({
placeholder: self.get('placeholder'),
tokenSeparators: [','],
multiple: true,
data: staticdata
});
So this issue was due to using select2 as custom ember component.
When you create an ember component you can either select an existing html tag e.g.
1. self.$('#selecttext').select2(...)
Where the html tag is located in your ember cli location templates/components/select2-component.hbs:
<select id="selecttext" class=" form-control input-md select2-hidden-accessible" multiple="" tabindex="-1" aria-hidden="true">
</select>
OR alternatively just initialize the component it self using:
2. self.$().select2(...)
When using approach 2. I am guessing select2 AJAX callback somehow loses the reference to select2 component. So that when you select a result from the list select2:selecting event is not generated and hence the result value is not selected.
I tested this using:
self._select.on("select2:selecting", function(e) {
alert('selecting');
});
However when you use approach 1. ajax callback does NOT lose the reference to the select2 component and generates the "select2:selecting" event and works as expected with the results being able to be selected.
Hence this works:
didInsertElement: function() {
var self = this;
var staticdata = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];
self._select = self.$('#selecttext').select2({
// note we are explicitly initialising select2 component on #selecttext
placeholder: self.get('placeholder'),
tokenSeparators: [','],
multiple: true,
tags: false,
//data: staticdata
ajax: {
url: "http://localhost:9990/api/v1/users/",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term // search term
};
},
processResults: function (data, page) {
return {
results: staticdata
};
},
cache: true
}
}); //select2 END
} //didInsertElement END

Resources