Sort data by time slot in javascript - javascript

I have to sort data coming from the server dynamically by differents fields. It is working perfectly with all the fields except by time slot field. I have to sort data by time slot field in ascedening order, the problem is that the time slot is string e.g: "09:00-09:59".
My sorting function is:
function sortArray(array: any[], direction: string, extractor: (any) => any): any[] {
return array.sort((e1, e2) =>
(direction === 'asc' && extractor(e1) > extractor(e2)) || (direction !== 'asc' && extractor(e1) < extractor(e2))
? 1
: -1
);
}
How can I fix it? If anyone know then please let me know. Thank you.

Your sortArray function is fine. You have to check sort.active and sort.direction are updating correctly.
Try like this:
console.log('this.sort.active', this.sort.active);
console.log('this.sort.direction', this.sort.direction);
And If they are not updating then this is the problem. Then revise your logic of updating these things.

Related

How to assign new key name to an object in an array of data?

In a React project, I've certain number of records which also contain input fields like Date and Text components in a Grid. I'm processing the date and text values in save function. All the records are fetched from JSON data, while saving date values its assigned to new key object but new one isn't getting updated with the old one. I have seen many similar posts but, none useful. Please refer to the code below:
Following is the function where I'm extracting both text and date values
const updateGrid = (data) => {
if (Array.isArray(allData) && allData?.length > 0) {
const tempData = allData;
tempData.map(x=> {
if(data.id === x.id) {
x.name = data.textVal
}
// Here I'm assigning the 'Establish' value with 'est'
if(data.id === x.id) {
x['est'] = x['Establish']
x.Establish = data.dateVal
}
})
setDataAll(tempData)
}
console.log('tempdataNew', dataAll)
}
As you can see from above picture, we have two keys, 'est' and 'Establish', but, I need only 'Establish', also getting undefined on 'name' when changed date value and vice-versa. What could be the best optimal solution to tackle this issue?
Please refer to Codesandbox --> https://codesandbox.io/s/jovial-aryabhata-95o2sy?file=/src/Table.js

Updating components based on sorted array. Angular (4.3)

Working with an array of data that we want to be able to sort for display in a component, and it doesn't seem to be sorting or updating the DOM, however I have a working code sample that properly demonstrates the concept, and it should be sorting, but in the angular app, it's simply not getting sorted.
The parent component that houses the original data stores the data on an Input parameter object called Batch, and the array we're sorting is on Batch.Invoices.Results. The event from the child component is fine, and the appropriate data is confirmed to bubble to the parent component.
The function that's supposed to sort the array looks like this:
public OnInvoiceSortChange({orderValue, orderAscending}){
console.log(`Invoice Sorting has been called. Value: ${orderValue} . Ascending? ${orderAscending}`);
console.log(`Before:`);
console.log(this.BatchViewModel.Invoices.Results.map(x => x.VendorName));
const sortingArray = [...this.BatchViewModel.Invoices.Results];
if(orderAscending){
const sorted = sortingArray.sort((a, b) => a[orderValue] > b[orderValue] ? 1 : 0);
this.BatchViewModel.Invoices.Results = sorted;
console.log('Sorted');
console.log(sorted.map(x => x.VendorName));
} else {
const sorted = sortingArray.sort((a, b) => a[orderValue] < b[orderValue] ? 1 : 0);
this.BatchViewModel.Invoices.Results = sorted;
console.log(sorted.map(x => x.VendorName));
}
console.log(`After:`);
console.log(this.BatchViewModel.Invoices.Results.map(x => x.VendorName));
}
All the console logs are for debugger visibility, and the output is this:
Where in my testing file (non-angular) looks like this:(where data is a direct copy of the array from the Angular app.
const ascendingData = [...data];
const descendingData = [...data];
const sortedDescending = descendingData.sort((a, b) => a['VendorName'] < b['VendorName']? 0 : 1)
const sortedAscending = ascendingData.sort((a, b) => a['VendorName'] > b['VendorName']? 0 : 1);
const vendorListAscending = sortedAscending.map(x => x.VendorName);
const vendorListDescending = sortedDescending.map(x => x.VendorName);
console.log(vendorListDescending);
console.log(vendorListAscending);
and the output looks like this:
So I see that the sorting should work, but it's just not happening in Angular.
How can I get the array sorted, and update the DOM as well?
The function you pass to sort is wrong. It is supposed to return a negative value for "less", a positive value for "greater" or zero for "equal". If orderValue is numeric then it's easiest to just return a[orderValue] - b[orderValue], if not then just change your 0 to -1.
(By the way, name orderKey could be a bit clearer maybe?)
I don't think angular has anything to do here, but I cannot tell now why you get different results. Anyway, your sort function is invalid (it states that a equals b, but at the same time b is greater than a), I hope fixing this function helps.

Trouble with Bootstraps typeahead in angular 5

I am having a difficult time getting Bootstraps typeahead in angular 5 working would appreciate some advice. The problem I have is that I don't know how to set the input field to equal the city + state for exaple "New york, NY" in bootstraps search method example. I am new to Typescript and the new fat arrow feature in JavaScript any help would be greatly appreciated.
model array of objects
public model: any;
example of data that I am getting
{
"city":"New York",
"latitude":40.7127837,
"longitude":-74.0059413,
"state":"New York",
"stateCode":"NY"
}
Search method here I am trying to set the location items to filter 'city,'+'state'
search = (text$: Observable<string>) => text$
.debounceTime(200)
.distinctUntilChanged()
.map(term => term.length < 2 ? [] : this.locationItems.filter(item => item.city.toLowerCase().indexOf(term.toLowerCase()) > -1).slice(0, 10));
The arrow function inside the last map in your chain needs to map (transform) the value of the string the user has typed into the search box to an array of items that will be presente to the user as suggestions.
You start nice, by askin if term is only one character long (or an empty string) and do nt even run the search, imediatelly returning empty array. For the other part, you need to find which items you want to present to the user.
This part depends on your business logic, but I assume that you want user to be searching by either state or stateCode? Anyway, this part is your business logic and you can change and improve it according to your busniess model. I'm giving a very simply function in the code below.
// util function
// returns true if the "term" can be used to match the "item" from your data
// change this according to your business logic
function matches(term: string, item: Item): boolean {
return item.state.toLowerCase().includes(term.toLowerCase())
|| item.stateCode.toLowerCase().includes(term.toLowerCase())
}
The lambda in the last map can be like this.
term => {
if (term.length < 2) {
return []
}
// arary of matching results
const matching = this.filter(item => matches(term, item))
// now we transform this to the format you specified
const formatted = matching.map(item => `${item.state}, ${item.stateCode}`)
return formatted
// you can also .slice(0, 10) here like you did in your example to keep the number of suggestions no more than 10
}

Optimizing IndexedDB query

I am using Dexie.JS to work with IndexedDB.
Currently, have a stupid query written as:
return db.events.each((element) => {
let d = element.cause.data;
if (d.hasOwnProperty('deleted') && (false == d.deleted) &&
d.hasOwnProperty('abbreviation') &&
d.hasOwnProperty('contents') && (d.abbreviation == key)) {
snippet = d.contents;
}
}).then(() => {
return snippet;
});
It is working correctly, but slow as molasses on a large database. Should I run each on a collection made from db.events with applied where? Would that improve performance?
Thank you
Yes if assuming your "key" variable is of an indexable type: string, number, Date, TypedArray or Array, you can optimize the query like this:
First, make sure to add the index "cause.data.abbreviation" on db.events:
db.version(2).stores({
events: 'yourPrimaryKey, cause.data.abbreviation'
});
Then, rewrite the query like this:
return db.events
// Let indexedDB sort out all items matching given key:
.where('cause.data.abbreviation').equals(key)
// Filter the rest manually using Collection.filter():
.filter(element => {
let d = element.cause.data;
return (d.hasOwnProperty('deleted') && (false == d.deleted) &&
d.hasOwnProperty('contents'));
})
// Execute the query and only return the first match:
.first();

Angular js inline conditions - detect number

Data come from db , and this html element is a ng-repeat
{{count}}
My Question
How can i show if else condition that,
If count is null (nothing count value) I would show 0 (count value should be zero) , else show original count value
I hope there are solution like {{count if '' else ''}}
You could have have logic in your view with {{count || 0}} or {{ count ? count : 0 }} but this makes maintainability more difficult and duplicates logic.
A better option would be to create a custom filter. This will allow you to define you condition in a single place and makes it re-usable in many directives but also testable.
.filter('isEmpty', function() {
return function (data) {
return (data === null || data === undefined) ? 0 : data;
}
});
And you would use it like
{{item | isEmpty}}
See fiddle: http://jsfiddle.net/fhfsex4v/2/
EDIT: Here's the docs for filter that will explain what its doing and also how to pass optional extra parameters into your filters and other cool stuff.
https://docs.angularjs.org/guide/filter
How about {{ count ? count : 0 }}

Categories

Resources