Unable to access nested JSON properties from handle bars template - ember.js

js with HandleBar, I have been using it for a couple of days now but I have hit a problem.
Basically i have the following json data:
{
"id":1009,
"parent_id":1007,
"template":"blog-post",
"path":"/blog-post/another-test-blog-post/",
"name":"another-test-blog-post",
"created":1389310922,
"modified":1389371901,
"created_users_id":41,
"modified_users_id":41,
"title":"Another Test Blog Post",
"headline":null,
"summary":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum quis lectus dui. ",
"image_caption":"Another Image Caption",
"images":{
"blog-sample-image-medium.png":{
"basename":"blog-sample-image-medium.png",
"description":"",
"tags":"",
"formatted":true,
"modified":1389352919,
"created":1389352919
}
},
"sub_heading":"Another Sub Heading"
}
It is valid data and I am able to obtain parameters and display within my handle bars template. However I am unable to access the properties within "images", I have tried also sorts of techniques and am unable to do so. Here is the part of my template in question:
{{#each item in model}}
<div class="media-element" {{#ifIsNthItem nth=3}} style="margin-right: 0px;" {{/ifIsNthItem}}>
<div style="skyiq-element-icon blog-element">
</div>
<div class="media-main-image grayscale" style="">
</div>
<p class="sub-heading">{{item.title}}</p>
<ul>
<li><i aria-hidden="true" class="skycon-user-profile"></i> By Liam Powell</li>
<li><i aria-hidden="true" class=" skycon-info"></i> 02/Dec/2013</li>
</ul>
<p>{{{item.summary}}}</p>
read more
<div class="skyiq-line"></div>
<i class=" skycon-share" aria-hidden="true"></i> Share
</div>
{{/each}}
So parameters such as item.summary display but I can not display item.images.1.basename for example.
Any help or a point in the right direction would be a great help.
Thanks in advance

Three things:
1) The way you're accessing it like this: {{item.images.1.basename}} makes me think you want to treat images like an array. You can't access items in an array using the index number in handlebars like you would in javascript. Ember provides helper properties called firstObject and lastObject on arrays that let you access the first and last object of the array. But, there isn't a secondObject which it looks like you want in the case you laid out. Typically the way you would access elements in an array is by iterating over them using an {{#each}}.
2) In the JSON you posted, images isn't an array but an object. So, you would access items on it like this: {{item.images.blog-sample-image-medium.png.basename}}.
3) Ember is likely going to not like the fact that the object key blog-sample-image-medium.png has a period in it, since that's how it figures out when it's time to access the next object. You should try and figure out how to get the period out of the keys name.

Related

Emberjs adding `.property()` in a function attribute of a controller/route

I'm trying to do the same as this question
My real question is why did he have to add .property() at the end of the function in the errorClass attribute? And can someone please point me to a documentation on how this work?
when I don't include the .property(), a stringed function of the attribute is placed as value in my template.
Handlebar:
<div class="tab-pane fade show {{loginActiveClass}}" id="login" role="tabpanel">
Expectation:
<a data-toggle="tab" href="#login" role="tab" class="nav-link active">
What happens when I discard the .property():
<a data-toggle="tab" href="#login" role="tab" class="nav-link function loginActiveClass() {
return this.get('page') === 'login' ? 'active' : '';
}">
With {{att}} in your hbs you access the value of the component's or controller's attribute/property named att.
By your description, your attribute loginActiveClass has a value of type function. This is what you get in your handlebars. Since the position where you use it only admits string values, you get the toString() representation of your value, which for a function is the function's code as string.
You cannot trigger actual evaluation of the function code by simply accessing it with {{att}} in your .hbs.
Adding .property() at the end gives you a computed property that does indeed evaluate the function and returns the evaluation result to the "caller". (Note that the preferred syntax for computed properties in Ember has changed a while ago to something more explicit. I recommend using eslint and eslint-plugin-ember to let your IDE or ember's cli inform you about best practices when appropriate.)
Also, in your specific example, the "logic" of the function is easily integrated into the hbs:
<div class="tab-pane fade show {{if (eq page 'login') 'active'}}" id="login" role="tabpanel">

How to get the LAST element in a list for Ember Acceptance Testing

When writing Acceptance tests, does anyone happen to know how one would select the LAST element in a list? I am testing the act of adding a new record to a list and would like to edit/delete the newly created record in my test.
I've tried to select the newly created record like this....
let newRecordLink = find('div.parent-list .list-group-item').last();
click(newRecordLink);
Which sorta works. It pulls the last element, but it busts out of my test and suddenly I'm on the actual page of the app I'm trying to test instead of remain within the test container.
Here is the relevant HBS code:
<div class="list-group parent-list">
{{#each model.owners as |item|}}
{{#link-to 'client.members.edit-owner' item.id class="list-group-item" id=item.id}}
<h4 class="list-group-item-heading">
{{item.firstName}} {{item.lastName}}
</h4>
{{/link-to}}
{{/each}}
</div>
You can use :last selector (https://api.jquery.com/last-selector/)
click('div.parent-list .list-group-item:last')
if it is an ember array u can use .get('lastObject')
I was struggling with this too, but I got it to work by using :last-of-type instead of :last

Remove accordion slide animation on page load

When my page loads the active accordion item slides open which causes the other elements on the page to also move for a second.
I'd like the active accordion item to render "already opened", but still retain the animation for when a user clicks on another accordion item, or even the originally opened item in cases where the user selects another item and then the original.
I cant find any css being used to do this, so maybe its something in the javascript? If so, how would I go about overriding this.
Any suggestions on how to accomplish this would be greatly appreciated!
Foundation Accordion: http://foundation.zurb.com/sites/docs/accordion.html
There's no simple solution from what I know, but you can override some attributes on load so that the active item is displayed by default. You'd have to begin with an accordion none of the items are active i.e. none of the accordion items have a class of .is-active:
Html:
<ul class="accordion" data-accordion data-allow-all-closed='true'>
<li class="accordion-item" data-accordion-item>
Accordion 1
<div class="accordion-content" data-tab-content>
Panel 1. Lorem ipsum dolor
</div>
</li>
<li class="accordion-item" data-accordion-item>
Accordion 2
<div class="accordion-content" data-tab-content>
Panel 2. Lorem ipsum dolor
</div>
</li>
<li class="accordion-item" data-accordion-item>
Accordion 3
<div class="accordion-content" data-tab-content>
Panel 3. Lorem ipsum dolor
</div>
</li>
</ul>
jQuery:
//Initialise the Foundation plugins
$(document).foundation();
function activateWithoutAnimation(itemIndex) {
//Get the accordion item according to its index (0 based)
var $accordionItem = $('.accordion-title:eq(' + itemIndex + ')');
//Set the aria attributes of the accordion item you want to appear
$accordionItem.attr('aria-expanded', 'true');
$accordionItem.attr('aria-selected', 'true');
//Set the attributes of the content.
$accordionItem.next().attr('aria-hidden', 'false');
$accordionItem.next().css('display', 'block');
//This is essential as it lets foundation know that the item is active (to re-allow toggling)
$accordionItem.trigger('click');
}
//Call the function.
activateWithoutAnimation(0);
There might be a better way to do the above, but from what I've read, there's no option that allows the animation to be disabled. I've tried overriding the defaults that Foundation provides to no avail.
Fiddle Demo
CSS Solution
If using the default helper class .is-active on initial load then some plain css can eliminate the slide open animation.
.is-active .accordion-content {
display: block;
}
https://jsfiddle.net/r6jvbohu/
CSS only (without losing the animation)
To always open the first item immediately while still keeping the animation, you can use the following code.
.accordion-item:first-of-type .accordion-content {
display: block;
}
The first item should still have the .is-active class to be consistent, but this removes the initial animation because we overwrite the display value from none to block. The JS still overwrites this state when another accordion item is clicked, resulting in the animation we want to keep.

how to get the list of values using list<> and session in asp.net mvc2

Hi I have a list of values contains different types of prices for the plans..
<div id="rs360">
<span class="font18">Rs.360</span> <span class="font20"></span>
</div>
<th width="20%" class="bdrL_blue valignT highlight">
<img src="../../Content/Images/Subscribe now on click.png" class="btn" onclick="return sms_confirm()"/>
<div id="rs1000">
<span class="font18">Rs.1000</span> <span class="font20"></span>
</div>
// the same button event...
when i click the button it should take the value of prices 360 ,1000.. then it redirects to the another page. on that page i click some payment options. so it should show which amount i select here like that...
i don't know what is the best way to do this? please give some ideas to do that?
So you want transfer the values 360, 1000... to your payment page?
[HttpPost]
public ActionResult YourActionName(double? price)
{
Session("PickedPrice")=price;
}
then your button event is call the controller with your value is price, for ex :
$.post("Controller/YourActionName",{ price : value_of_your_price });
In your payment's page you can use it by using Session("PickedPrice"), when you done, reset Session("PickedPrice").
This is my solution, it's may not the best way and I just newbie but I want to help you. Try!

dojo: Show or hide divs based on selection in a list

Is there a simple way to accomplish this using dojo (jQuery would be easier for me but I have to use dojo): I have a simple unordered list. I don't want dojo to style the list (as it might if I used some widget). When I click a link on the list I want to show a div associated with the link. Then if I click another link in the list the first div hides and that one shows.
<div id="content">
<h2>Header</h2>
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
</ul>
<div id="sub_content1" style="display:none;">
<h3>Sub Content Header 1</h3>
<p>Lorem ipsum veritas britas conflictum civa</p>
</div>
<div id="sub_content2" style="display:none;">
<h3>Sub Content Header 2</h3>
<p>Lorem ipsum mobius ceti</p>
</div>
<div id="sub_content3" style="display:none;">
<h3>Sub Content Header 3</h3>
<p>Lorem ipsum citrus pecto</p>
<ul>
<li>Lemons</li>
<li>Limes</li>
</ul>
</div>
</div><!-- end of #content -->
So in fact you're creating your own tabcontainer? If you really want to do it yourself you should probably need something like this:
require(["dojo/ready", "dojo/on", "dojo/dom-attr", "dojo/dom-style", "dojo/query", "dojo/NodeList-dom"], function(ready, on, domAttr, domStyle, query) {
ready(function() {
query("ul li a").forEach(function(node) {
query(domAttr.get(node, "href")).forEach(function(node) {
domStyle.set(node, "display", "none");
});
on(node, "click", function(e) {
query("ul li a").forEach(function(node) {
if (node == e.target) {
query(domAttr.get(node, "href")).forEach(function(node) {
domStyle.set(node, "display", "block");
});
} else {
query(domAttr.get(node, "href")).forEach(function(node) {
domStyle.set(node, "display", "none");
});
}
});
});
});
});
});
I'm not sure how familiar you are with Dojo, but it uses a query that will loop all links in lists (with the dojo/query and dojo/NodeList-dom modules) (you should provide a classname or something like that to make it easier). Then it will, for each link, retrieve the div corresponding to it and hide it, it will also connect a click event handler to it (with the dojo/on module).
When someone clicks the link, it will (again) loop all the links, but this time it's doing that to determine which node is the target one and which isn't (so it can hide/show the corresponding div).
I made a JSFiddle to show you this. If something is still not clear you should first try to look at the reference guide of Dojo since it really demonstrates the most common uses of most modules.
But since this behavior is quite similar to a TabContainer, I would recommend you to look at the TabContainer reference guide.