dynamically load formly typeahead options - angularjs

I am using Angular Formly, and try to build a form with a Select field which allows to pick the state of a country.
The second field is a typeahead field, which allows to enter valid area names belonging to this state.
However, I am failing to dynamically change the typeahead options array.
I have taken the Typeahead type definition from the Formly Examples, and works fine with a static array of options:
formlyConfig.setType({
name: 'typeahead',
template: '<input type="text" ng-model="model[options.key]" ' +
'uib-typeahead="item for item in to.options | filter:$viewValue | limitTo:8" ' +
'class="form-control">',
wrapper: ['bootstrapLabel', 'bootstrapHasError'],
});
This is my form definition:
$scope.selectZoneFormFields = [
{
key: 'stateid',
type: 'select',
templateOptions:{
label: Constants.DIVPOL,
valueProp: 'id',
labelProp: 'nombre',
options: StatesManager.get()
}
},
{
key: 'zoneName',
type: 'typeahead',
templateOptions: {
label: 'Zona',
options: $scope.zoneNames
}
}
];
Then, I watch changes in stateid and refresh $scope.zoneNames:
$scope.$watch('geo.stateid', function(newValue, oldValue) {
if (newValue === undefined || newValue.length !== 2 || newValue === oldValue )
return;
console.log(' !!! STATE change detected: ' + oldValue + '-->' + newValue);
refreshZones(newValue);
});
The problem is that the options for the typeahead field remain those which are loaded at the beginning (initial value of $scope.zoneNames)
I have tried to use a controller inside formly field definition, but with no success.
Ideas?

{
key: 'zoneName',
type: 'typeahead',
templateOptions: {
label: 'Zona',
options: []
},
expressionProperties: {
'templateOptions.options': function($viewValue, $modelValue, $scope){
$scope.to.options = []; //set to an empty array
if($scope.model.stateid) { //if the state has been selected
$scope.to.options = //whatever code you use to get the zones
return $scope.to.options; //return the options
}
}
}
}

Related

dynamic angular filter in ui-grid grouped custom cell template

I need a cell table with more than one value. I made a construct for ui-grid options, a custom template for the cell and few css lines. It works and permit me to decide if value must stay in the same line or in more than one line.
Custom template:
var template =
'<div class="ui-grid-cell-contents crm-group">'+
'<div class="crm-group-row" ng-repeat="rowFields in col.colDef.fields">' +
'<div class="crm-group-col" ng-repeat="colField in rowFields" ng-if="row.entity[colField.name]">' +
'<span class="title" ng-if="colField.descr">'+
'{{colField.descr}}: '+
'</span>' +
'<span class="content">'+
//"{{row.entity[colField.name] }}"+ //without filter
"{{row.entity[colField.name] | colField.cellFilter}}"+ //<-- HERE doesn't work
'</span>' +
'</div>'+
'</div>' +
'</div>';
option structure:
{ field: 'group',
name: 'Group',
width: '**',
fields : [
[
{
name: "age",
descr: "Num",
cellFilter : "floatToFixed:'2'",
},
{
name: "email",
descr: "Email",
},
],
],
cellTemplate: template
},
Now i need to apply a possible different filter to each value. So i set it on the field structure. In this case i want apply a custom filter to the first field value.
Filter:
app.filter('floatToFixed', function () {
return function (input, number) {
console.log(input);
console.log(number);
if (!input)
return null;
if (!number)
return input;
else
return parseFloat(input).toFixed(parseInt(number));
}
});
But it doesn't work. Here the plunker.
Help is appreciate.
First of all, you have incorrect format after pipe | - name of the filter can't contain dot, what you could do is have a filter that applies filter from a string, that's the solution I can came up from top of my head:
http://plnkr.co/edit/by8vQBgeau0823akwQvu?p=preview
.filter('applyFilter', function($filter) {
return function(input, filter) {
var filterToApply = filter !== undefined ? filter.split(':') : undefined;
return filterToApply === undefined ? input : $filter(filterToApply[0])(input, parseInt(filterToApply[1], 10))
}
})
and then in html
"{{row.entity[colField.name] | applyFilter:colField.cellFilter}}"

Search text from cell template not working in ui-grid

I have defined a conditional cell template for one of the column. Its displaying the data correctly but I am not able to search for the text in the cell template.
Here is my plunkr:
https://plnkr.co/edit/TDX5jtPord1hkzCVaw3L?p=preview
var template1 = '<div class="">' +
'<div class="" ng-if="COL_FIELD > 30">Greater </div> ' +
'<div class="" ng-if="COL_FIELD < 30"> Lesser </div> ' +
'</div>';
In the template I have put the condition that.. if COL_FIELD > 30 then then write Greater.. or else write Lesser. And now I should be able to search for the Greater or Lesser in Number column.
A solution could be to add a property on your data like :
$http.get('data.json').success(function(data) {
data.map(function(item) {
item.greaterLesser = item.amount > 30 ? 'Greater' : 'Lesser';
});
$scope.gridOptions.data = data;
});
and then instead of using the amount with a template, just bind on this property.
$scope.gridOptions = {
enableFiltering: true,
columnDefs: [{
field: 'name',
width: 70
}, {
field: 'greaterLesser',
name: 'Number',
width: 90,
}, {
field: 'amount',
name: 'Currency',
cellFilter: 'currencyFilter:this',
}]
};
Here is the updated plunker
Edit
If you want to use the template, you could implement the search function yourself. You can add the filter option to your field and implement the condition function. Something like:
filter: {
condition: function(searchTerm, cellValue) {
var value = cellValue > 30 ? 'greater' : 'lesser';
var result = value.search(searchTerm.toLowerCase());
return result > -1;
}
}
Here I used the search function but you could use match or some other function.
Here is a demo plunker
I used the below code to make search work
field: 'EmpId',
displayName: 'Employee Type',
cellTemplate: '<div style="cursor:pointer" class="ui-grid-cell-contents">{{grid.appScope.GetEmployeeType(row)}}</div>',
filter: {
condition: function (searchTerm, cellValue,row,column) {
var value = $scope.GetEmployeeType(row);//same function that you use to display value in cell Template
return (value.toLocaleLowerCase().indexOf(searchTerm.toLocaleLowerCase())>-1);
}
}

Error when passing filter parameter in Uigrid with cell nav

I have a editable Uigrid with ui-grid-cellnav directive to enable edit on focus. I also have a filter to display value instead of id in the dropdown.
<div ui-grid="gridOptions" ui-grid-edit ui-grid-cellnav class="grid"></div>
JS
$scope.gridOptions.columnDefs = [
{ name:'name', width:100 },
{ name:'age', width:100},
{ name: 'gender', displayName: 'Gender', editableCellTemplate: 'ui-grid/dropdownEditor', width: '20%',
cellFilter: "griddropdown:this", editDropdownIdLabel:'id',
editDropdownValueLabel: 'gender', editDropdownOptionsArray: [
{ id: 1, gender: 'male' },
{ id: 2, gender: 'female' }
] }
];
An error occurs whenever the dropdown value is modified. It seems the filter parameter is passed as a string instead of actual object, but not sure why. Works ok if I remove the cellnav directive.
Plnkr
Thanks in advance!
Interesting, I played with it a little bit and it looks like you are getting the desired results, just that occasionally ui-grid likes to pass a string as a parameter instead of the object.
If you add a check for a string in your filter it looks like you will still be getting the desired results, that's if I am understanding properly:
String check to add:
if (typeof context !== 'string') {}
Full Filter:
.filter('griddropdown', function() {
return function (input, context) {
if (typeof context !== 'string') {
var map = context.col.colDef.editDropdownOptionsArray;
var idField = context.col.colDef.editDropdownIdLabel;
var valueField = context.col.colDef.editDropdownValueLabel;
var initial = context.row.entity[context.col.field];
if (typeof map !== "undefined") {
for (var i = 0; i < map.length; i++) {
if (map[i][idField] == input) {
return map[i][valueField];
}
}
} else if (initial) {
return initial;
}
}
return input;
};
});

unable to update the ngmodel of select list

Case :
I am trying to update the value of ng-model inside the controller but it is not working and i wonder why , any idea ?
HTML :
<select ng-model="dumm" ng-options="item.name as item.type for (name, item) in availableFilters" ng-change="selectFilter()"></select>
JS :
$scope.selectFilter = function () {
$scope.availableFilters[$scope.dumm].visible = true;
$scope.dumm = "";
};
$scope.availableFilters = {
name: {
type: 'Name',
name: 'name'
},
producttype: {
type: 'Product type',
name: 'producttype',
data: $scope.xxx
},
status: {
type: 'Status',
name: 'status',
data: $scope.unitStatusTypes
}
};
$scope.dumm should be an object rather than a string, otherwise the binding won't work - this fact is quite obscure in Angular's docs. The binding should look like this:
<select ng-model="dumm.value"...
and the variable's definition:
$scope.dumm = {value: ""};

checkbox states disappear on pagination of kendo grid

Not sure if I am doing this correctly. But I bind a kendo grid with array data of objects, where each object has a Boolean property (i.e. either true or false).
For the user I display it as a checkbox with the checked state showing the true state and vice versa. If you check something in the page 1; go to the page 3; check a few rows; and go back to page 1, the state of the checkbox defaults to how it was at the time it was loaded.
Here is the code snippet I've used.
$(function () {
var ds = new kendo.data.DataSource({
transport: {
read: {
url: '/echo/json/',
type: 'POST',
data: {
json: JSON.stringify(students)
}
}
},
pageSize: 5
});
var kgrid = $("#grid").kendoGrid({
columns: [
{
field: 'name',
title: 'Name'
}, {
field: 'age',
title: 'Age'
}, {
field: 'place',
title: 'Place'
}, {
field: 'hasCar',
title: 'Owns Car',
template: function (data) {
return '<input type="checkbox" ' + (data.hasCar ? 'checked' : '') + '/>';
}
}],
height: 240,
pageable: true
});
$('#btnload').click(function () {
var grid = kgrid.data('kendoGrid');
grid.setDataSource(ds);
$('#grid-display').show();
});
$('#btnrefresh').click(function(){
ds.read();
console.log('refresh');
});
$('#btnlist').click(function(){
var res = $('#result');
kgrid.find('tr td:last input:checked').each(function(i, e){
var name = $(e).closest('tr').children().first().text();
res.append('<p>' + name + '</p>');
console.log('execute');
});
});
});
How to persist the state on pagination?
Ps: fiddle to work with: http://jsfiddle.net/deostroll/2SGyV/3/
That is because the changes you are doing stays there in the grid only - not in kendoDataSource. Here MVVM is not done. So you have to change appropriate value in dataSource each time you click the checkbox.
When you select another page in kendoGrid, it fetches data from dataSource, and then display it the grid. Unless and untill that dataSource is changed, you can't see the changes done in the grid.
PS: Had there is any field for Id in dataSource I would have updated jsfiddle myself
UPDATE
Check this Updated jsfiddle
I have updated template for checkbox
template: function (data) {
return '<input type="checkbox" ' + (data.hasCar ? 'checked' : '') + ' data-name="'+ data.name + '"' +'/>';
}
Now checkbox will have name of the data. You can change it with id. On change event, update your dataSource accordingly on each checkbox click.
$('#grid-display input').live('change', function(){
alert($(this).attr('data-name'));
//update the data source here based on the data-name attribute u're getting
});
Use databound event in the kendo Grid.
Not sure below code work will work for you or not. But similar code worked for me
function OnDataBoundEventMethod(e) {
var view = this.dataSource.view();
for (var i = 0; i < view.length; i++) {
if ([view[i].hasCar]) {
this.tbody.find("tr[data-uid='" + view[i].uid + "']")
.addClass("k-state-selected")
.find(".row-check-box")
.attr("checked", "checked");
}
}
}

Resources