incorrect res.render using express and node - arrays

I want to render the following using express and jade:
function(output) {
for (i=0;i<output.entities.length;i++){
console.log(output.entities[i].uuid);
}
res.render('errCodes.jade', {title : 'Error Codes', entry: output.entities});
},
the jade looks like so:
items = entry
each item, i in items
li #{item}
The console log looks nice, but no matter what I try, I can't get the jade page to look nice. At the moment, there are two links that read
[object Object]
[object Object]
which is expected. However, I want two links of the ID to show up, but every time I've tried I either get each character of the ID as its own link, or the aforementioned object, object. Any help would be greatly appreciated.

is your original indentation correct? or is it just here on SO that it looks wrong?
items = entry
each item, i in items
li #{item} // this should be further right
You can use pure jade to achieve the same:
items = entry
each item, i in items
li
a(href="/#{i}") #{item}
if your array looks like the following
output.entities = [{ uuid: 1234 }, { uuid: 5678 }];
your jade should look like this
items = entry
each item, index in items // iterate over array
li
a(href="/#{index}") #{item.uuid}
index will be 1,2,3,4,... etc.

Related

Mutating array within an array (Polymer iron-list)

I currently have an iron-list within another iron-list. The parent's data comes from a firebase-query element, and the child's data is computed from each parent item. The db structure and code looks a bit like this:
DB: [
category1: [
itemId1: {
price: 10,
title: "title"
}
]
]
<iron-list id="categoryList" items="{{categories}}" multi-selection as="category">
<template>
<div class="category-holder">
<iron-list id="{{category.$key}}" items="{{_removeExtraIndex(category)}}" as="item" selection-enabled multi-selection selected-items="{{selectedItems}}" grid>
<template>
<div class$="{{_computeItemClass(selected)}}">
<p>[[item.title]]</p>
<p>[[item.price]]</p>
</div>
</template>
</iron-list>
</div>
</template>
</iron-list>
After selecting any number of items, the user can tap on a fab to batch edit the price. This is where I'm having issues. I can't figure out how to access the correct child iron-list in order to call list.set...I'm currently trying the following very nasty method:
var categories = this.$.categoryList;
var categoryItems = categories.items;
(this.selectedItems).forEach(function(item) {
var index = item.itemId;
categoryItems.forEach(function(itemList, categoryIndex) {
if (itemList[index]) {
categories.set('item.' + categoryIndex + '.price', 10);
}
}, this);
}, this);
I'm iterating over the selected items in order to extract the item index and then iterating over the parent iron-list data (categoryItems) in order to check if the given item exists in that subset of data. If so, then I use the category index and attempt to call set on the parent iron-list using the given path to access the actual item I want to edit. As expected, this fails. Hopefully I've made myself clear enough, any help would be appreciated!
EDIT #1:
After much experimenting, I finally figured out how to correctly mutate the child iron-list:
(this.selectedItems).forEach(function(item) {
var list = this.$.categoryList.querySelector('#' + item.category);
var index = list.items.indexOf(item);
list.set(["items", index, "price"], 30);
}, this);
A couple of things worth noting. I'm using querySelector instead of the recommended this.$$(selector) because I keep running into a "function DNE" error. But now I have another problem...after calling the function, the value gets updated correctly but I get the following error:
Uncaught TypeError: inst.dispatchEvent is not a function
Here's a picture of the full error message:
I see the light, hopefully someone can help me out!
OK, I'll take a shot at this. I think the following happens, and I guess this based on how dom-repeat works:
var categories = this.$.categoryList;
var categoryItems = categories.items;
You take the variable that the iron-list is based on, but setting one array to another just creates a reference in javascript. As soon as you update categoryItems, you also update this.$.categoryList.items. When you later sets the new value, iron-list will do a dirty check and compare all subproperties, and because they are equal (because ... reference), the iron-list wont update the dom.
What you should do is to make sure it's a totally new copy and the way of doing that is to use JSON.parse(JSON.stringify(myArray)).
Further on, one major flaw I see in your code is that you're using querySelector to select an element, and then manipulate that. What you should do is to use this.categories and only that variable.
So your method should look something like:
// Get a freshly new array to manipulate
var category = JSON.parse(JSON.stringify(this.categories);
// Loop through it
category.forEach(category) {
// update your categoryList variable
}
// Update the iron list by notifying Polymer that categories has changed.
this.set('categories', category);

ReactJS : Manipulating State doesn't render child components properly

I have three Components "MyApp", "Candidate" and "Courses" and the data is passed from MyApp to Courses.
The data is as such
var data = [{
name : "azhar",
courses : ["Compilers", "Algorithms", "Data Structures"]
}, {
name : "Jenny",
courses : ["Design", "UX"]
}];
And the ReactComponents are rendered as such below :
<MyApp>
<Candidate>
<Courses>
<Courses>
<Courses>
</Candidate>
</MyApp>
Problem : There is a button to add a new Candidate, When clicked I add new Candidate to the state of MyApp. When clicked I see Child components do not render proper data.
Added JSFiddle : https://jsfiddle.net/69z2wepo/8587/
Really hoping someone gives a good explanation, because this is a simple use case.
Thanks
When you create an array of JSX elements like you do with this.state.data.map() you should always include a key attribute that is unique for that position in the array. Note that it shouldn't be something that can change like the index in the array, or the name of the candidate (since there can be duplicates).
If you add an id property on your candidate objects, and create a new id when you add a candidate, it should work: https://jsfiddle.net/qzy3sr6w/2/
Here's a good explanation: http://blog.arkency.com/2014/10/react-dot-js-and-dynamic-children-why-the-keys-are-important/
The TL;DR of that post is that the reason it works for push but not with unshift is because if you don't specify key, React will use the index of the array as key (not exactly true, but close enough). And since you're adding to the beginning of the array, it will use the index 0 which it previously used for another component, meaning that the new first element will get the second elements courses.
I don't think it is a good idea to use react.state directly, as you are doing here:
this.state.data.unshift({
name : "Alice",
courses : [] // No courses for her.
});
Better use additional variable like this:
var candidates = this.state.data;
candidates.push({
name : "Alice",
courses : [] // No courses for her.
});
this.setState({
data : candidates
});
Here is a JSFiidle: https://jsfiddle.net/69z2wepo/8597/

Getting text of element without including text of sub-element with jsoup

I'm using jsoup to parse HTML. There are list items that look like this:
<li><span class="chk">X</span>Category Name</li>
I want to get the text of the li NOT including the text of the span. So I want to get "Category Name" without the "X". (If I invoke the text() method on the li element, I get "XCategory Name".) How can I exclude the sub-span?
ownText() method will help you here.
Document document = Jsoup.parse("<ul><li><span class=\"chk\">X</span>Home</li><li><spanclass=\"chk\">X</span>Category Name</li></ul>");
Elements elems = document.select("li");
for(Element elem : elems){
System.out.println(elem.ownText());
}

Restangular - Removing property from element

Im trying to remove a property element before doing the submission of that element.
$scope.changeTitle = function(song, title){
song.title = title;
delete song.label;
song.put();
}
When doing so it seems that the property "label" is removed. When I do the PUT operation the object actually has the property label.
// This is the object I'm sending (checked from the chrome dev tool - network)
{
artist: "XXXXX"
title: 'XX'
label: []
}
Is there any way to remove a property from an element?
If you inspect the object's put method in Developer console, you'll find that the referenced object is actually your original object (even after changes). In order fix the reference, use Restangular.copy() before you manipulate the object.
Earlier when you wrote something along the lines of:
$scope.song = restangular.one(song, 1).get().$object;
You should instead write:
$scope.song = restangular.copy(restangular.one(song, 1).get().$object);
To see the related issue, checkout: https://github.com/mgonto/restangular/issues/55
You can use underscore's _.omit function (http://underscorejs.org/#omit)
song = _.omit(song,'label');

rails 3 find a value in a params array

I am using jQuery UI Sortable to sort some rows on my website.
Here is my view:
<section class="data-list">
<article id="item_<%= item.id %>" class="data sortable">
<!-- stuff goes here -->
</article>
</section>
Here is my JS:
$('.data-list').sortable({items: '> .data'}).bind('sortupdate', function() {
var release = getUrlVars()["id"];
$.ajax({
type: 'POST',
data: $(this).sortable("serialize"),
url: '/release_items/'+ release +'/prioritize'
});
});
This creates a params['item'] array that looks like this:
["1537", "1536", "1540", "1541", "1542", "1543", "1544", "1545", "1547", "1546"]
Here is my controller code:
def prioritize
#release = Release.find(params[:id])
item = #release.release_items
item.each do |i|
i.priority = params['item'].index(i.id.to_s).to_i + 1
i.save
end
end
My problem is that i have several release_items that are distinguished by an item_type column. And as it stands now i currently don't have a good way in my controller to filter by item_type in my #release = Release.find(params[:id]) line.
What i would like to do is make sure in the item.each do |i| loop that the priority is only set IF the item is in the params['item'] array. How would i do that? Please let me know if this is not clear enough. Thanks!
EDIT 1:
For every release, there are n number of release items. THose release items are separated for display on the site by their item_type column (e.g., General, Project, Data, Patch). So on the site there are 4 different lists of items and i want to be able to sort those 4 lists individually. Like i stated above, the params['item'] array being passed to the prioritize action in the controller has only the items that need to be sorted, which is want i want.
The problem i'm running in to is that the first two lines in the prioritize action will get all of the release items, not just the ones in the params['item'] array. The values in the array are the IDs of the release items that need to be sorted. Instead of getting all release items, i want to only get the items that are in the params['item'] array. I do have a ReleaseItem model as well i can select from. So, i'm trying to do this: (i know this isn't the correct code, just for clarity sake)
item = ReleaseItem.find(conditions: "id in params['item']")
Does that make a little more sense? I appreciate your help!
I think I understand what you are trying to do...
def prioritize
#release = Release.find(params[:id])
items = #release.release_items.where("id IN (?)", params['item'])
items.each_with_index do |item, index|
item.priority = index + 1
item.save
end
end

Resources