JavaScript - Undo sorting of an Array - javascript

I'm making a sortable table. The table data is from an array of objects. I need to be able to sort the array based on the properties
an object looks like this:
{
"AbsenceReservationID": 7220,
"Name": "DGM",
"Code": "ARBEIDSONGEVAL WP",
"RequestState": "Goedgekeurd",
"From": "2017-03-21T00:00:00+01:00",
}
I'm using lodash, so I can easily sort my array using the following syntax:
asc:
myArr = _.sortBy(myArr , "Name");
desc:
myArr = _.sortBy(myArr , "Name").reverse;
However I'm stuck at the last sorting method. I need to be able to undo the sort but I can't figure out a good way to do this. Here's how it would work:
1st click - sort asc
2nd click - sort desc
3rd click - remove sorting
on this property
I think the hard part is when the user sorts on mutliple properties, so for example
How can I achieve this removal of a property sort?

You basically have three choices:
Don't offer the "unsorted" option
Remember the original order (perhaps by adding a property for it), and for the "unsorted" option, sort on that property
For instance, you can add an originalIndex property:
_.forEach(myArr, function(e, i) { e.originalIndex = i; });
Then myArr = _.sortBy(myArr, "originalIndex"); will get the original order back.
Keep the original array somewhere (since _.sortBy creates a copy), and use the original array again when you want the "unsorted" version

You can use to create an original copy:
var oldArr = myArr.slice(); // gives you a new copy.
You can use oldArr after sorting.

Where are you getting the data from initially? (service)
If it is coming from a service call - would recommend simply re-calling that service and setting the data equal to the data retrieved again.
If you don't want to make a call to the service again, simply create two objects in JS sortingData and unsortedData. Then when you use the lodash method, simply apply it only to the sortingData array. On the third click, do
sortingData = unsortedData;
Where are you getting the data from initially? (manually created)
The same approach of having two objects applies here. Once the data has been created, before you allow sorting to be done, set the unsortedData to the data that you have generated. e.g.
unsortedData = data;

Related

How to change the array elements proprity in javascript?

I am adding the new task using following javascript code:
function addTask(name, important){
alert(important);
const newTask = {id: "todo" + nanoid(), name:name, completed:false, important:important, checked:false};
setTasks([...tasks, newTask]);
console.log(setTasks)
}
Now, I would like to add the last task on the first place of the application. May I ask please how to make it possible?
setTasks([newTask, ...tasks]);
Is the cleanest way to add items in front, however later on it may prove inconsistent (after saving into db for example and retrieving the list from db), personally I would use array.sort() method and sort the array by creation date or / and by "important" key. This way, no matter how you push an item into array, they will be always in correct / needed order.

How to increment a map value in a Firestore array

I have a firestore firebase database , in which I have a collection users
there is an array in the collection and in the array there is a map
in map there is a field qty.. I want to increment that qty value..
using increment doesnt help as the qty is inside a array index
db.collection("users").doc(checkId).update({
myCart: firebase.firestore.FieldValue.arrayUnion({
qty: firebase.firestore.FieldValue.increment(1),
}),
this is the error Output =>
Uncaught (in promise) FirebaseError: Function FieldValue.arrayUnion() called with invalid data. FieldValue.increment() can only be used with update() and set()
My answer below won't work, given that the qty is in an array. The only way to update an item in an array is to read the entire document, update the item in the array, and then write the entire array with the updated item back to the document.
An alternative would be to use a map instead of an array, and then update the qty using the approach outlined in my (old, and non-working) answer below 👇
You need to specify the full path to the field you're trying to update. So I think in your case, that'll be:
db.collection("users").doc(checkId).update({
"myCart.0.qty": firebase.firestore.FieldValue.increment(1)
}),
The field you want to update is embedded in an array. In this case, you can't use FieldValue.increment(), since it's not possible to call out an array element as a named field value.
What you'll have to do instead is read the entire document, modify the field in memory to contain what you want, and update the field back into the document. Also consider using a transaction for this if you need to update to be atomic.
(If the field wasn't part of an array, you could use FieldValue.increment().)
As of today (29-04-2020)... this is tested by me.
Suppose my data structure is like this:
collection: Users
Any document: say jdfhjksdhfw
It has a map like below
map name: UserPageVisits
map fields: field1,field2,field3 etc
Now we can increment the number field in the map like below:
mapname.field1 etc...
That is use the dot operator to access the fields inside the map just like you would do to an object of javascript.
JAVA Code (Android), update the field using transactions so they can complete atomically.
transaction.update(<documentreference object>,"UserPageVisits.field1",FieldValue.increment(1));
I have just pushed a version of my app which uses this concept and it's working.
Kudos !!
My Best Regards
Previous answers helped me as well, but dont forget about the "merge" property!!! Otherwise it will overwrite your entire array, losing other fields.
var myIndex = 0;
const userRef = db.collection('users').doc(checkId);
return userRef.update({
'myCart.${myIndex}.qty': admin.firestore.FieldValue.increment(1)
}, {
merge: true
});

How do I iterate through objects stored in a firebase array in JavaScript?

At the moment I am storing a few objects in Firebase. After successfully retrieving the items from Firebase and storing them in a firebaseArray, I want to further thin out the unwanted elements by deleting the elements in the firebaseArray that do not have the desired property. Consider my code at the moment, that does not do as wanted, however there are no errors in the console:
var querylatestPosts = firebase.database().ref("Topics");
$scope.latestPosts = $firebaseArray(querylatestPosts);
console.log($scope.latestPosts) ;
$scope.latestPosts.forEach(function(el) {
if ($scope.checkWorldview(el) == false) {
delete $scope.latestPosts.el ;
}
});
(Note I am unable to log 'el' in the console, nor does the forEach seem to execute, as I can log nothing in the function in the console)
The 'checkWorldview' function behaves as expected when elements are fed in different instances and returns false if the required property is not present in the element under consideration. Thus if the function returns false, I want to delete the specific element in $scope.latestPosts that does not contain the wanted property.
I hope this is clear, thank you in advance for any help you can offer!
The way you are using the $firebaseArray isn't recommended by the docs (see here), which state that $firebaseArray is read only and should not be manipulated.
So you have a few options:
Instead of filtering the array on the client-side, you should modify the query you're using to retrieve data from Firebase to only get elements that have the desired property (ex: use 'equalTo' in the query)
OR
Don't use a $firebaseArray because you're not using it in the way it was intended. Use a regular, good ol' fashion JavaScript array instead.
** Also, just a general comment: don't delete elements from an array as you loop through it as this is generally bad practice (we don't expect arrays to have elements added/removed while we loop through them). Instead, use Array.filter.

Ember filterBy - using more than one value to filter

How can I use more than one value to filter a list using the filterBy function?
My scenario is - I have a list of consoles which I want to filter based on the console_id.
Unfortunately, I don't have control over the JSON so each consoles has a different ID. I would like to loop through the Console IDs within the nested assignedConsole JSON and then filter through the root assignedConsole JSON.
I can get the console ID of the first object and place it into the filter but I don't know how I can use two values
I have created a emberjs bin to demonstrate my problem: http://emberjs.jsbin.com/kojute/2/
After some clarification from my previous answer, I realized you want to filter by console instead of filtering the assignedConsole values. My suggestion is to add a selectedConsole property on the controller, and display the array of assignedConsoles for the selected console.
Working JSBin: http://jsbin.com/nuroyuvuta/9
EDIT: See my other answer for the working solution!
I would suggest creating a computed property on your model or your controller that flattens that nested structure for you:
allConsoles: function() {
return this.get('consoles')
.mapProperty('assignedConsoles').reduce(function(a, b) {
return a.concat(b);
})
.uniq();
}.property('consoles.#each')
This will first get all of the items from the consoles property, then map all of their assignedConsoles to an intermediate value, which is then reduced by adding all the assignedConsoles together. The final uniq() call just removes any duplicates found in the array.

How to compare Two data stores in Dojo

I have two data store of type dojo.data.ItemFileReadStore.One of the data store having old data and other one having new data.How can i compare these two data stores?
I call the fetch method on both of the stores and did a compare but didn't work for me.
IF a same item can be in two stores, then you could fetch all items from one store, on Complete, foreach item, otherStore.isItem(someItem) which will return a boolean :)
Have you tried that?
The format used by ItemFileReadStore is not a requirement of the dojo.data API. The
format it uses is designed to work well for the specific situations
ItemFileReadStore is used for, which are moderately sized data sets that can be easily
represented in a JavaScript Object tree.
Structure of Input Data Format
{
"label": "some attribute", // Optional attribute used to indicate which attribute on
an item should act as a human-readable label for display purposes.
"identifier": "some attribute", // Optional attribute used to indicate which
attribute on an item acts as a unique identifier for that item. If it is not defined,
then the ItemFileReadStore will simply number the items and use that number as a
unique index to the item.
"items:" [ // The array of JavaScript objects that act as the root items of the data
store
{ /* Some set of name/value attributes */ },
{ /* ... */ },
...
]
}
solution 1: in our application we have used this method:
dojo.require("dojo.json");
_equal: function(objA, objB) {
return dojo.json.stringify(objA) === dojo.json.stringify(objB);
}
the data inside objects should also have the same order, otherwise comparison will fail.
solution 2: but in dojo 1.8 they have introduced dojox/mvc/equals function.
it compares two given objects.
please also consider using dojo/store instead of deprecated dojo/data

Categories

Resources