custom getCellEditor - extjs

I use custom CellEditor in my grid:
getCellEditor: function(colIndex, rowIndex) {
var field = this.getDataIndex(colIndex);
if (field == 'value') {
if ( type == 3 ) {
return this.editors['number'];
} else if ( type == 1 ) {
return this.editors['select'];
} else if ( type == 4 ) {
return this.editors['checkbox'];
}
}
return Ext.grid.ColumnModel.prototype.getCellEditor.call(this, colIndex, rowIndex);
}
},this);
type - this is record.get('type') from grid.store. How to know type in this getCellEditor ?
(I don't want to use global variable :) )

You can use the rowIndex parameter, so to access the 'type' for the current row in your grid:
grid.store.getAt(rowIndex).data.type

You will have need to have defined the type in the field definition, From there, you can use the row index to get the Record.
var record = store.getAt(rowIndex);
for(var i = 0; i<record.fields.length; i++) {
if(record.fields[i].name == 'Your Field') {
alert(record.fields[i].type);
}
}
This is untested but shows how you can test for the type of a given field in the record

Related

sorting an array where the second property may be nonexistent

I need to sort a table for an Angular project. The catch is that for some of the values in the table, I need to sort by a direct property of the objects in the array, but for others I need to sort by a child of that direct property.
For example, I have associate.lastname for one column and associate.client.name for another column. I'm trying to do all of this in one method and I've got a working method in TypeScript.
This is the sortBy method in my component's class:
sortBy(option: SortOption, sortedBy: string) {
const props = option.split('.');
const parent = props[0];
const child = props[1];
const asc = this[sortedBy];
if(!child) {
this.associates.sort((associateA, associateB)=> {
if (associateA[parent] < associateB[parent]) {
return asc === true ? -1 : 1;
} else if (associateB[parent] < associateA[parent]) {
return asc === true ? 1 : -1;
} else {
return 0;
}
});
} else {
this.associates.sort((associateA, associateB)=> {
if (associateA[parent][child] < associateB[parent][child]) {
return asc === true ? -1 : 1;
} else if (associateB[parent][child] < associateA[parent][child]) {
return asc === true ? 1 : -1;
} else {
return 0;
}
});
}
this[sortedBy] = !this[sortedBy]
}
SortOption is an enum, and the value may or may not have a . in it. I split on that period to get the parent and child properties, and then sort the array based on whether the parent or the child exists.
Now what I'm wondering is if there's a better, drier, way to do this. You'll notice the code in both the if and the else statement are almost exactly the same, with the exception of the child property being used or not, but I can't think of a cleaner way to do this.
Is there a better way?
You might want to extract a sorting key function:
let sortingKey: (associate: any) => number; // or some other type, depends on your code
if (child) {
sortingKey = (associate) => associate[parent][child];
} else {
sortingKey = (associate) => associate[parent];
}
After that you will be able to simply write:
this.associates.sort((associateA, associateB)=> {
if (sortingKey(associateA) < sortingKey(associateB)) {
return asc === true ? -1 : 1;
} else if (sortingKey(associateB) < sortingKey(associateA)) {
return asc === true ? 1 : -1;
} else {
return 0;
}
});

AngularJS multiselect custom filter not working as intended

In an AngularJS record display (with filters) I have a multiselect array of territories that a user can select from to find out if a certain item is available in a certain territory.
The array returns a list of values such as
['001','010','200']
based on the ID of the territories selected. This is then checked against a JSON list of records which has a JSON value looks like this
territoriesnotavailable: "001, 085, 090"
Each record either has this set to null, or has a list from one to many numbers.
I currently use the following code (customFilter) which works perfectly if you only select ONE value.. it basically makes the item filter out if the territory selected in the multiselect is in the list of territoriesnotavailable
function CustomTerritoryFilter() {
return function(data, query) {
if (query.length === 0) return data;
if (data) return data.filter(function(item) {
for (var i = 0; i < query.length; i++) {
var queryitem = query[i]["id"];
if(item.territoriesnotavailable) {
stringB = item.territoriesnotavailable;
} else {
stringB = 'xxxxxxxx';
}
stringA = queryitem;
if (!(stringB.indexOf( stringA ) > -1)) {
return data;
}
}
});
return [];
};
}
So if I choose only one filter (resulting in a query of ['010'] for example. and this appears in territoriesnoavailable for the record.. it vanishes as expected.. but if I choose any value that is NOT in territoriesnotavailable the item appears again.. i need the record to vanish if ANY selected territory appears in the list regardless of any that do not
function CustomTerritoryFilter() {
return function(data, query) {
if (query.length === 0) return data;
if (data) return data.filter(function(item) {
for (var i = 0; i < query.length; i++) {
var queryitem = query[i]["id"];
if(item.territoriesnotavailable) {
stringB = item.territoriesnotavailable;
} else {
stringB = 'xxxxxxxx';
}
stringA = queryitem;
if (!(stringB.indexOf( stringA ) > -1)) {
return false;
}
}
return true;
});
return [];
};
}
This is the code that I settled on. It basically sets a flag as 1 (show) and then checks each number in the filter.. if there is just one occurance of the number in the list, the flag is set to zero. At the end of the check data is shown if the flaG REMAins as 1
function CustomTerritoryFilter() {
return function(data, query) {
if (query.length === 0) return data;
if (data) return data.filter(function(item) {
var flag = 1;
for (var i = 0; i < query.length; i++) {
var queryitem = query[i]["id"];
if(item.territoriesnotavailable) {
stringB = item.territoriesnotavailable;
} else {
stringB = 'xxxxxxxx';
}
stringA = queryitem;
if (stringB.indexOf( stringA ) > -1) {
flag = 0;
}
}
if(flag === 1) {
return data;
}
});
return [];
};
}

Angular2 - search in array inside of an array

I have an array of events and I have a search() function (below) that filters through it. Currently it only filters for name or date. Within my payload I have an array of tags, and I'm trying to figure out how to include it in the filtering of this. My current work-around is buttons that re-run the /event endpoint with search params which I don't like.
search(array: any[], query: string, excludeProps?: string|string[], dateFormat?: string) {
if (!query || !this._objArrayCheck(array)) {
return array;
}
const lQuery = query.toLowerCase();
const isoDateRegex = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; // ISO UTC
const dateF = dateFormat ? dateFormat : 'medium';
const filteredArray = array.filter(item => {
for (const key in item) {
if (item.hasOwnProperty(key)) {
if (!excludeProps || excludeProps.indexOf(key) === -1) {
const thisVal = item[key];
if (
// Value is a string and NOT a UTC date
typeof thisVal === 'string' &&
!thisVal.match(isoDateRegex) &&
thisVal.toLowerCase().indexOf(lQuery) !== -1
) {
return true;
} else if (
// Value is a Date object or UTC string
(thisVal instanceof Date || thisVal.toString().match(isoDateRegex)) &&
// https://angular.io/api/common/DatePipe
// Matching date format string passed in as param (or default to 'medium')
this.datePipe.transform(thisVal, dateF).toLowerCase().indexOf(lQuery) !== -1
) {
return true;
}
}
}
}
});
return filteredArray;
}
I tried adding an addition else after the date finder and leverage a for() loop on item.tags but it seems typescript doesn't really let you do a traditional for loop.
What is the actual method of handling this within Ang/Typescript?
Update
search(array: any[], query: string, excludeProps?: string|string[], dateFormat?: string) {
if (!query || !this._objArrayCheck(array)) {
return array;
}
const lQuery = query.toLowerCase();
const isoDateRegex = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; // ISO UTC
const dateF = dateFormat ? dateFormat : 'medium';
const filteredArray = array.filter(item => {
for (const key in item) {
if (item.hasOwnProperty(key)) {
if (!excludeProps || excludeProps.indexOf(key) === -1) {
const thisVal = item[key];
if (
// Value is a string and NOT a UTC date
typeof thisVal === 'string' &&
!thisVal.match(isoDateRegex) &&
thisVal.toLowerCase().indexOf(lQuery) !== -1
) {
return true;
} else if (
// Value is a Date object or UTC string
(thisVal instanceof Date || thisVal.toString().match(isoDateRegex)) &&
// https://angular.io/api/common/DatePipe
// Matching date format string passed in as param (or default to 'medium')
this.datePipe.transform(thisVal, dateF).toLowerCase().indexOf(lQuery) !== -1
) {
return true;
} else if (
typeof thisVal === 'string'
) {
for (var i=0; i < item.tags.length; i++) {
if (thisVal === item.tags[i]){
return true;
}
}
}
}
}
}
});
return filteredArray;
}
I was thinking something similar to this but it doesn't seem to be returning anything.
sample Payload
// collection: events
{
"_id" : ObjectId("59dda4b702ac8332bcb90921"),
"title" : "Gantt Chart Example222dsda",
"location" : "Home",
"startDatetime" : ISODate("2018-01-01T12:30:00.000-05:00"),
"endDatetime" : ISODate("2018-01-02T12:30:00.000-05:00"),
"description" : "dsad",
"viewPublic" : true,
"tags" : [
"Gaming",
"Social",
"home",
"misc"
],
"__v" : NumberInt("0")
}
My function should be able to match 'gantt' to the title and still show the row. It should also be able to match 'gaming', 'social' 'home' etc and pull this same record due to the tags. It should be able to pull from the start or end date time.

how to check a value in array object angularjs

i have this array object:
$scope.datas.labels=['10','20','30']
and also i have a function return an array object like this:
response.labels=['10','20','30','50','100','80']
i created a function which recieve the last result..but what i want is to check if a value in response.labels exists in the $scope.datas.labels i dont want to insert it..to avoid duplicated data in $scope.datas.labels, how i can do that??
i tried this but i didnt work:
$scope.concatToData=function (response) {
if($scope.datas.labels=='') {
$scope.datas.labels = $scope.datas.labels.concat(response.labels);
}else {
var i;
for (i = 0; i < $scope.datas.labels.length; i++) {
alert('qa' + JSON.stringify($scope.datas.labels));
alert('res' + JSON.stringify(response.labels));
if ($scope.datas.labels[i] !== response.labels[i]) {
$scope.datas.labels = $scope.datas.labels.concat(response.labels[i]);
} else {
break;
}
}
}
$scope.datas.datasets = $scope.datas.datasets.concat(response.datasets);
}
Try this it will work as per your expectation and requirement.
var arr1=['10','20','30'];
var arr2=['10','20','30','50','100','80'];
for (var i in arr2) {
if(arr2[i] != arr1[i]) {
arr1.push(arr2[i]);
}
}
document.getElementById('result').innerHTML = arr1;
#result {
font-weight:bold;
}
<div id="result"></div>
Take a look at the lodash library, you'll find it useful, and this will be useful for you too:
let common = _.intersection($scope.datas.labels, response.labels);
if (_.size(common) && _.includes(common, 'myValue')) {
// You have a winner;
// This item (myValue) is in both;
} else {
}
Hope that helps.
You can also try that:
var response = ['foo', 'fabio'];
var labels = ['foo'];
var result = response.filter((value) => {
return labels.filter((rs) => {
return rs == value;
}).length == 0;
});
It will return only the data that does not exists on $scope.datas.labels.

Angular ng-repeat filtering

I have a deeply nested object. I have some records which contain 2 fields that show keys of object properties. I also have select needed to search records by property of object and input to search by key of object. So if I choose option1 and type in input some text, it will be shown the matches in the first field (not second!). And it's similar for second field.
How I try to realize:
I wrote a filter http://plnkr.co/edit/z9DEmfYz2grW9UonLcFK?p=preview
.filter('appFilter', function() {
return function(value, select, input) {
var result = [];
input = input.toLowerCase();
var reg = new RegExp(input,'g');
if (angular.isArray(value)) {
if (input === '' || $scope.isFiltering) {
return value;
} else if (select.value === 'Sequence') {
for (let i = 0; i < value.length; i++) {
if (value[i].Sequence.toLowerCase().match(reg)) {
result.push(value[i]);
}
}
return result;
} else if (select.value === 'ID') {
for (let i = 0; i < value.length; i++) {
if (angular.isArray(value[i].Document)) {
for (let j = 0; j < value[i].Document.length; j++) {
if (value[i].Document[j].ID.toLowerCase().match(reg)) {
result.push(value[i]);
}
}
}
}
return result;
} else {
console.log('error');
}
}
}
})
In controller I set to select's ng-model first option: $scope.selectParameter = $scope.parameter[0];
In debug I set to input parameter some value (123 for example).
So I searching record by first field that contains 123 value. And result finds and pushes the object. But in browser shows anything.
What's the problem? And I can't avoid the empty option with '?' value in my select :(
UPDATED
Nearly solve my problem: http://plnkr.co/edit/z9DEmfYz2grW9UonLcFK?p=preview
It filters by appropriate field and input value. But I faced with another troubles.
When input is empty it doesn't show any record. And second is when I choose second option (ID) filter duplicates some records.
Also I try to switch off filter without clearing the input text by clicking on checkbox.
It's what I want to do but it doesn't work:
else if (input === '' || $scope.isFiltering) {
return value;
}
$scope.isFiltering is ng-model for checkbox input
I tried using angulars default filter. I'm not sure if this is exactly what you want, but maybe it helps a little.
.filter('appFilter', function($filter) {
return function(value, select, input) {
if( !angular.isDefined(input) || input.length < 1) {
return value;
}
// Angulars "filter" lets you pass in a object-structure to search for nested fields.
var query =
(select.value === 'Sequence') ?
{Sequence:input} : {Document:{ID:input}};
return $filter('filter')(value, query);
}
})
http://plnkr.co/edit/Egkw9bUvTPgooc0u2w7C?p=preview

Resources