I am building a website which requires the Autocomplete to load results from ajax, so I decided to choose the angular material Autocomplete and its working fine.
Until now my requirement was to show the search results of one type, lets say I need to show the search results of country names, but now my requirements changed to show the country names and the state name and this cause me to make two different groups one of country and the another of state, i did not found a solution of show to modify the angular material autocomplete custom template.
Please see the image attached:
Hi consider this version, modified solution from above answer if it helps,
https://jsfiddle.net/sachinshukla5/9xykgvs6/78/
Basically just adding an additional element in the items array which is needed to be dispalyed at specific index.
var states = getStates().filter(function(item) {
item.isFirst = false;
return (item.state.toUpperCase().indexOf(searchText.toUpperCase()) !== -1);
});
var countryName = "";
angular.forEach(states, function(item, key){
if(countryName != item.country){
countryName = item.country;
states.splice(key,0, {
"isFirst" : true,
"state": " ",
"country": countryName
});
}
})
deferred.resolve(states);
}, 200);
I have create one solution which can help you.
Please find link
Angular Material Autocomplete custom template
Here the logic is, find out first element in the searched list and add country name on it
var states = getStates().filter(function(item) {
item.isFirst = false;
return (item.state.toUpperCase().indexOf(searchText.toUpperCase()) !== -1);
});
var countryName = "";
angular.forEach(states, function(item, key){
if(countryName != item.country){
countryName = item.country;
item.isFirst = true;
}
})
You have to work on styling part line adding divider between values.
Please let me know if I can help you in other context
Related
We have an Ag-Grid table with row selection via the built in checkbox functionality. The check boxes are conditionally displaying via the isRowSelectable options:
isRowSelectable: function (rowNode) {
return rowNode.data ? rowNode.data.published === false : true;
}
The published column is being updated as part of a modal called from another column. A redrawRows is being called when the modal is closed:
modal.result.then(() => {
const row = params.api.getDisplayedRowAtIndex(params.rowIndex as number);
//this.gridApi?.redrawRows([row] as any);
this.gridApi?.redrawRows();
});
The display values in the row are being updated when the modal is closed, however, the checkbox is not appearing when the published value is set to false. If I hang a breakpoint in Dev Tools the isRowSelectable code does not appear to be hit.
Any suggestions would be much appreciated.
Cheers,
-John
Can you try this and see if it works?
let itemsToUpdate = [];
let data = rowNode.data;
// modify data fields
// Ex: data.field1 = "new value";
itemsToUpdate.push(data);
this.gridApi.applyTransaction({update: itemsToUpdate});
https://www.ag-grid.com/javascript-data-grid/data-update-transactions/
Use refreshCells
this.gridApi?.refreshCells({force:true});
https://www.ag-grid.com/react-data-grid/view-refresh/#redraw-rows
i am learning angular. so i am not good in angular. i am showing data in tabular format with the help of ng-repeat. i have one dropdown and textbox for filter data showing by ng-repeat. fields name are populated in dropdown. so user will select field name and put corresponding value in textbox and search will perform accordingly and data will be shown.
my code is working partially. basically some kind of problem is there in SearchList function. the problem is when trying to search by id then SearchList is not working properly. so looking for help. what to fix in the code. my js fiddle https://jsfiddle.net/tridip/rnoo3bqc/6/
$scope.SearchList = function(row) {
if ($scope.selectedFieldName && $scope.searchText) {
var propVal = row[$scope.selectedFieldName.toLowerCase()];
if (propVal) {
return propVal.toUpperCase().indexOf($scope.searchText.toUpperCase()) > -1;
} else {
return false;
}
}
return true;
};
working version url
https://jsfiddle.net/tridip/rnoo3bqc/8/
You need to convert the id's from number to string, e.g. by concatenating an empty string:
var propVal = row[$scope.selectedFieldName.toLowerCase()] + '';
the problem was with id that's a numeric field and hence toUpperCase() was failing for it.
if (propVal) {
propVal.toString().toUpperCase().indexOf($scope.searchText.toUpperCase()) > -1;
} else {
return false;
}
I'm new to extjs and I'm looking for a way to add some custom message under my combobox field.
Depending on some conditions (eg. value selected) the message needs to have different text and/or style.
I could play with errorEl associated with my combobox and change it's message/style depending on the state, but this doesnt look like a good approach.
Are you aware of any plugin allowing to add such a message, or is there a shorter way to do this?
Thank you for your suggestions. I ended up writing my own plugin, which then I attached to combobox.
I added new element after error element and I changed messages based on proper combobox events.
afterCmpRender : function() {
var me = this, cmp = me.getCmp();
var messageWrapper = {
tag : 'div'
};
var messageEl = cmp.errorEl.insertSibling(messageWrapper, "after");
cmp.messageEl = messageEl;
Ext.Array.each(me.messages, function(message) {
var messageConfig = {
tag : 'div',
style : {
display : 'none'
}
};
var newElement = messageEl.insertSibling(messageConfig, "after");
newElement.setHTML(message.value);
newElement.addCls(message.classes);
me.registerMessageEvents(me, cmp, message, newElement);
});
}
I almost always use multiple elements for this, and would not make an attempt to change the field.
Depending on your context, which you didn't provide, I'd say you could have a look at:
Ext.form.field.Display
Ext.form.Label
Ext.tip.Tip
Ext.tip.QuickTip
I'd work with the class Ext.tip.Tip.
You can create
Ext.create('Ext.tip.Tip', {
id: 'myTip',
header: false
});
and then
var tip = Ext.getCmp('myTip');
tip.update('your custom tip message');
tip.showBy(comboboxComponent);
You could also use showAt(..) instead of showBy.
For more information look into the Docu
Here is a Fiddle link to an example.
I'm having an issue using a dropdown that is populated with ng-repeat option values or even when using ng-options.
Basically I'm pulling a list of subsidiaries from the database. I then have a dropdown to choose a company, which in turn should populate the subsidiary dropdown with subsidiaries of the chosen company. Since many of the subsidiaries are of the same company, if I try and pull the the company name in ng-repeat, I get the same company several times. So I have created a custom filter that filters out the companyName and companyID of each company listed only once.
Everything works in the theory that when I change the value of the company dropdown, the correct subsidiaries are listed. However the value shown in the company box is stuck on the first option listed and will not change. If I remove the custom filter and allow it to list all the repeat names, the box displays correctly.
My first thought is to make a separate HTTP call that would just get companies from my companies table, but I would think I want to limit HTTP calls to as few as possible. Plus it would seem that I should be able to accomplish this.
What concept am I not grasping that prevents this from displaying correctly when I use my filter and what should I do to fix this?
thanks
HTML:
<div class="col-sm-5">
<select ng-model ="parentCompany" name="company">
<option ng-repeat="company in companies | uniqueCompanies:'companyName'" value="{{company.id}}" >{{company.name}}</option>
</select>
</div>
<div class="col-sm-5">
<select name="subsidiary">
<option ng-repeat="subsidary in companies" value="{{subsidary.subID}}" ng-hide="$parent.parentCompany !== subsidary.companyID">{{subsidary.subName}}</option>
</select>
</div>
Controller:
getCompanies();
function getCompanies(){
$http.get("get.php?table=getcompanies").success(function(data) {
$scope.companies = data;
});
}
Filter:
.filter("uniqueCompanies", function() {
return function(data, propertyName) {
if (angular.isArray(data) && angular.isString(propertyName)) {
var results = [];
var keys = {};
for (var i = 0; i < data.length; i++) {
var val = data[i][propertyName];
var val2 = data[i]['companyID'];
if (angular.isUndefined(keys[val])) {
keys[val] = true;
results.push({'name':val, 'id':val2});
}
}
return results;
} else {
return data;
}
};
});
Sample Data :
[{"subID":null,"subName":null,"companyID":"1","companyName":"DWG"},
{"subID":null,"subName":null,"companyID":"2","companyName":"Vista"},
{"subID":"1008","subName":"Data Services","companyID":"3","companyName":"Medcare"},
{"subID":"1009","subName":"Companion","companyID":"3","companyName":"Medcare"},
{"subID":"1010","subName":"GBA","companyID":"3","companyName":"Medcare"},
{"subID":"1011","subName":"PGBA","companyID":"3","companyName":"Medcare"},
{"subID":"1013","subName":"Health Plan","companyID":"3","companyName":"Medcare"},
{"subID":"1014","subName":"PAISC","companyID":"3","companyName":"Medcare"},
{"subID":"1015","subName":"CGS","companyID":"3","companyName":"Medcare"}]
You are creating new objects in your filter with different properties so they will be different every time. You can you track by as mentioned by others. Since filters are executed every digest cycle you may want to set up a $watch and only create a new list of unique companies when your companies change. I actually get the 10 $digest() iterations reached error without doing this.
$scope.$watchCollection('companies', function(newValue) {
$scope.filteredCompanies = $filter('uniqueCompanies')($scope.companies,
'companyName');
});
You could also set a watch on parentCompany and create the list of subsidiaries only when it changes, as well as clear out the value you have for subsidiaryCompany:
$scope.$watch('parentCompany', function(newValue) {
$scope.subsidiaries = [];
for (var i = 0; i < $scope.companies.length; i++) {
var c = $scope.companies[i];
if (c.companyID === newValue) {
$scope.subsidiaries.push(c);
}
}
$scope.subsidiaryCompany = undefined;
});
I may not be fully understanding you're issue here, but it looks like you could filter the data when you get it. Such as ...
function getCompanies(){
$http.get("get.php?table=getcompanies").success(function(data) {
$scope.companies = data.reduce(function (prev, cur) {
// some code for skipping duplicates goes here
}, []);
});
}
Array.reduce may not be the best way to get a new array without duplicates, but that's the general idea, anyway.
How do I reset my ExtJS filters in my grids. More specifically, how do I get the header to honour the changes to the filtering.
ie. This works fine :
grid.store.clearFilter();
But the header rendering is all wrong. I need to get into all the menu objects and unselect the checkboxes.
I am getting pretty lost. I am pretty sure this gives me the filterItems :
var filterItems = grid.filters.filters.items;
And from each of these filter items, i can get to menu items like so :
var menuItems = filter.menu.items;
But that's as far as I can get. I am expecting some kind of checkbox object inside menu items, and then I can uncheck that checkbox, and hopefully the header rendering will then change.
UPDATE :
I now have this code. The grid store has its filter cleared. Next I get the filterItems from grid.filters.filters.items and iterate over them. Then I call a function on each of the menu items.
grid.store.clearFilter();
var filterItems = grid.filters.filters.items;
for (var i = 0; i<filterItems.length; i++){
var filter = filterItems[i];
filter.menu.items.each(function(checkbox) {
if (checkbox.setChecked)
checkbox.setChecked(false, true);
});
}
The checkboxes do get called, but still nothing is happening :(
Try this code:
grid.filters.clearFilters();
This should take care of both the grid and its underlying store.
When you do
grid.store.clearFilter();
it can only clear the filters on the store but the grid's view doesn't get updated with that call. Hence to handle it automatically for both the grid's view as well as the grid's store, just use
grid.filters.clearFilters();
Hope it helps!
Cheers!
Your update help me but you forget the case where you have input text instead of checkbox.
So this is my addition of your solution:
grid.filters.clearFilters();
var filterItems = grid.filters.filters.items;
for (var i = 0; i<filterItems.length; i++){
var filter = filterItems[i];
filter.menu.items.each(function(element) {
if (element.setChecked) {
element.setChecked(false, true);
}
if(typeof element.getValue !== "undefined" && element.getValue() !== "") {
element.setValue("");
}
});
}
When you use grid wiht gridfilters plugin
and inovoke
grid.filters.clearFilters();
it reset applyed filters, but it don't clean value in textfield inside menu.
For clean textfield text you can try this:
grid.filters.clearFilters();
const plugin = grid.getPlugin('gridfilters');
let activeFilter;
if('activeFilterMenuItem' in plugin) {
activeFilter = plugin.activeFilterMenuItem.activeFilter
}
if (activeFilter && activeFilter.type === "string") {
activeFilter.setValue("");
}