Underscore JS, Grouping by an array Attribute. - javascript

I'm trying to use Javascript to group an array by one of it's attributes.
Essentially I have a list of e-mail templates, and I'm trying to group them by the category that they are in so that I can make a collapsible accordion with it later.
I think I might have the syntax of underscore JS wrong, or I'm addressing my array incorrectly. Currently I am calling groupby using the following command:
console.log(_.groupBy(result, 'im_category'));
but my array looks like the 'im_category' property is hidden under the attributes function. I'm not sure how to get there.
I've attached my console.log of what the array looks like and what happens when I run that command. (I get three different objects when I should get 2 if it's working correctly. )

Your im_category is a property of the attributes object in your businessEntity - _.groupBy is looking for properties of businessEntity. You need to create a function as iteratee:
var grouped = _.groupBy(result, function (item) {
return item.attributes.im_category;
});
http://jsfiddle.net/jwnzh8w0/

Related

JavaScript - Undo sorting of an Array

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;

Pass index to custom orderBy function

This might be simple and stupid but I can't seem to figure it out. I have created a ng-repeat structure that I use multiple times on different objects. Basically, I iterate through elements in an array inside those objects and depending on some variable I either need to apply custom orderBy, or leave it in the original order.
So I've created that custom orderBy like that:
<li ng-repeat="tag in filter.tags | orderBy: customSort(filter.customSort)">
Basically, filter object contains array of tags and a boolean variable that states if custom sort needs to be applied. Within my customSort function I check if passed on parameter is true and perform that custom sort. But if it's false - I cannot seem to be able to output tags in their original order in that array.
I cannot pass $index because at that point it is always 0, it only becomes index inside that ng-repeat tag. I cannot do something like that filter.tags.indexOf(tag) because tag doesn't exist yet.
I'm kinda stuck, is there a way to apply orderBy conditionally?
Further explaination:
I iterate over an array of tags and print their localized values, some of those tags should be in their original order, some should be ordered alphabetically in their localized version. So my stripped custom sort does something like this:
$scope.customSort = function(language) {
return function(tag) {
return $scope.tags.[language][tag];
}
}
So far this is the only solution I came up with, I will wait a little to see if anyone answers with a better one before I mark this one as correct.
I had to pass the entire array to the sorting function, along with boolean variable used to determine whether original order or custom sort is desired and then used indexOf like this:
$scope.customSort = function(perform, tags, language) {
return function(tag) {
if (!perform) return tags.indexOf(tag);
return $scope.tags.[language][tag];
}
}

How to use linq.js except

I am trying to use linq.js to remove a object from a array. I am customizing highcharts and i need to modify the series. I identified the object I want to remove using .where. When I run it through the Except it is not throwing any errors. it just doesn't filter the object out.
object that I want to remove from the series
var matchingSeries = Enumerable.From(series).Where('x => x.options.id == "' + item + '"').First();
trying to get this to work
var newSeries = Enumerable.From(series).Except(matchingSeries).ToArray();
I would like to use the id as the identifier. the id is nested in matchingSeries.options.id
In LINQ in C#, Except deals with two lists. Remove the First() call from your first statement to return a list of items that can be matched against the first list.

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.

jQuery Id Selection and Dynamic Arrays

I have some code I'm struggling with. The good news is the code working as intended for a single instance; after some thought I've decided to feature multiple of these image selectors on a page. This works but the ugly approach of duplicating the code doesn't scale well (e.g. what if you want 50 of these on there?) The snag I've hit is how I can refer to a specific array. Is an array even an ideal solution for this?
The Objective
I have a series of images that a user may select from, up to X amount. The selected image ids are stored in an array and the image is added to a "selected images pool". This occurs by using an onClick for the slider, I obtain the Id from the element attributes. This is where I'm getting stuck.
var dataArray = $(this).closest("[id^=carousel]").data('array');
var slideCounter = $(this).closest("[id^=carousel]").data('counter');
slideCounter = dataArray.length;
The slideCounter returns the length of the string, not the array elements. How can I tell this code to refer to a particular array? See the fiddle for a better idea of the markup and code: jsFiddle
I have no doubt that there is a better approach. I'm relatively new to front end work, I'd appreciate any insights, I've burnt some brain cells on this, thanks!
From looking at your HTML, it looks like when you do this:
var dataArray = $(this).closest("[id^=carousel]").data('array');
what you're trying to do is to read the name of an array with .data() and then somehow turn that name (which is a string) into the array that's in your variable. My guess is that there's probably a better way to structure your code rather than putting javascript variable names in your HTML. I'd probably put a key name in the HTML and then store the arrays in an object where you can access them by that key name at any time.
Without trying to refactor your code, here's an idea for what you were trying to accomplish:
If selectedSlidesIdArray1 is a global variable, then you can do this:
var dataArray = window[$(this).closest("[id^=carousel]").data('array')];
Using the [stringVariable] notation on an object, lets you access a property by a literal string or a variable that contains a string. Since all global variables are also properties on the window object, you can do it this way for global variables.
If selectedSlidesIdArray1 is not a global variable, then you should probably put it in an object and then you can do this:
var dataArray = yourObj[$(this).closest("[id^=carousel]").data('array')];
Instead of trying to translate an arbitrary string into a JavaScript variable of the same name, why not just use another array? You can have nested arrays, which is to say an array of arrays.
Thus, instead of selectedSlidesIdArray1, selectedSlidesIdArray2, etc., you would have one selectedSlidesIdArray with sub-arrays, which you could then pull the index for using a data attribute.

Categories

Resources