Dynamic property query in handlebars [duplicate] - templates

This question already has an answer here:
Handlebars.js: index access to global.json from a loop
(1 answer)
Closed 2 years ago.
I am trying to get a property of an object in handlebars dynamically dependent upon the pid that the #each loop is currently on. I have tried the following code but the value isn't getting populated at all. I'm imagining there's some sort of context problem, but as I'm quite new to handlebars, I don't know the way to go about doing this.
<div class="card-deck">
{{#each entries}}
{{! backend only hidden comments}}
<div class="card">
<img class="card-img-top img-fluid" src="/userimgres/{{pid}}/0.jpg" alt="Card image cap">
<div class="card-body">
<h5 class="card-title"><strong>{{name}}</strong></h5>
<p class="card-text">{{desc}}</p>
</div>
<div class="card-footer">
<small class="text-muted">Posted {{../ago.[pid]}} ago (ID: {{pid}})</small>
</div>
</div>
{{/each}}
</div>
My ago object is setup with the key as the pid and the value as a string describing, in human readable format, how long it's been since a specified date/time.
For what it's worth, it's generated by a separate function from a constant object, hence why it's not in the same object to begin with. It looks like this:
{
'1000': '2 hours ago',
'1001': 'a month ago',
'1002': '3 days ago',
'2000': '4 days ago',
'2001': '12 days ago',
'2002': '4 months ago',
'2003': 'a month ago'
}
When I change the code to be static and query {{../ago.[1001]}}, I receive my string for that specific ID. Since the code relies on a for each, however, this obviously returns the same exact string for the other entries.
How can I modify this statement to dynamically query the ago object for a key's value - the key being defined by the pid that is currently being iterated through in the #each (i.e. what I'm doing elsewhere in this codeblock by simply calling {{pid}})?
I have tried {{../ago.[{{pid}}]}} and several other arrangements but none seem to work.
Many thanks in advance for any help, and I'm happy to clear anything up if this is unclear.

You must use the lookup helper as documented here
From the docs:
The lookup helper allows for dynamic parameter resolution using Handlebars variables.
This is useful for resolving values for array indexes.
{{#each people}}
{{.}} lives in {{lookup ../cities #index}}
{{/each}}```
In the instance of this question, you can simply change this example from using the current index to use a variable (in this case pid) located in the same context that the #each loop is in.
{{lookup ../ago pid}} should work for you. It gets the object ago from the parent context, then based off the #each loop's current iteration of entries.pid, it gets the value from ../pid for the key of pid it's on.
In other situations, you may need to continue reading the documentation linked in this answer for other ways of using the locate helper:
It can also be used to lookup properties of object based on data from the input. The following is a more complex example that uses lookup in a sub-expression to change the evaluation context to another object based on a property-value.
{{#each persons as | person |}}
{{name}} lives in {{#with (lookup ../cities [resident-in])~}}
{{name}} ({{country}})
{{/with}}
{{/each}}

Related

Bindable Iterables in a template

I have an Aurelia application up and running and I am using a template with bindable parameters.
<template bindable="textitems">
${textitems}
<section id="one" class="wrapper">
<div class="inner flex flex-3">
<div class="flex-item left">
<div repeat.for="textitem of textitems">
<p>${textitem}</p>
</div>
</div>
</div>
</section>
</template>
And I am passing it in like this
<attractor textitems="${attractors}"></attractor> where attractors is the array of items.
This basically is not behaving as I would like for it to.
${textitems} is spitting out the right content in this case one,two but - when it gets to the repeat for section - aurelia complains that it (textitems) is not iterable.
I have since found out that this is because it becomes a string of the array being output. So it becomes 'one,two' rather than ['one','two']
If so there must be a better way for me to pass this data down into the template.
Bindable definately seems the cleanest method, but Id love to be proven wrong.
Thanks for your time, no one seems to have been presented with this issue yet, but I am just getting started, and I think it will help others.
I needed to add .bind to the bindable section in the original template call.
textitems="${attractors}" - Caused the passed value to be the array rendered as a string.
textitems="attractors" - Caused the passed value to literally be the word attractors
textitems.bind="attractors" - Caused the passed value to be the array - as intended.
(suggested by Jesse de Bruijne)
One can presume that Aurelia needs .bind to handle the item as the object it is and not a string rendering of it. The ${} syntax causes the template to spit out the text rendering of whatever the thing is and just putting the name of the variable just spits out the name itself.

How to pass parameters/attributes to a component in EmberJs when using "as" operator

I have a structure to invoke my component in this way, in a .hbs file
{{#myComponent as |section|}}
{{#if (eq section "section1")}}
this is the content for the first section <br>
{{else if (eq section "section2")}}
Some content for section two <br>
More content for second section <br>
{{/if}}
{{/myComponent}}
I want to be able to pass some parameters along, like this
{{#myComponent as |section| param1="xyz" param2=true}}
It is resulting in a parse error while build.
How can i still pass parameters to be accessed by the component in this scenario?
Thanks in advance!!
Figured that the entire component object has to be used, and then the "as" key word follows. Like this
{{#myComponent param1="xyz" param2=true as |section|}}

Pass current route to template

I've been playing around with golang for a couple of weeks now, and recently started to look into the revel framework.
In other languages/frameworks that I've used, it's always been possible to check what the current route is from within the template. Something that made it easier for me to keep things like navigation in a separate template file, and just do this:
<!-- in header template -->
<ul class="nav">
{{ if eq .req.action "App.Index" }}
<li class="active"><a href="#">
{{ else }}
<li><a href="{{url "App.Index" }}">
{{end}}
Home</a></li>
<!-- other links here -->
</ul>
This isn't the actual code I'm writing, but I hope this makes it clear what the idea is: Have a template for the navigation handy, and set classes/links according to which action is the current one.
After some time going through the source code, and a number of golang template examples, I couldn't quite see any way in which the current action or anything else is exposed to the template.
To get around this, I'm currently using a func interceptor which automatically sets a render argument for me:
func prependRoute(c *revel.Controller) revel.Result {
c.RenderArgs["_current_route"] = c.Action
return nil
}
This is working fine, but it feels a bit hacky. I think I'm probably missing something really obvious that would allow me to reserve func interceptors for when I really need them.
The question, then, is simple: What is the correct, and most reliable way to find out what the current action is in a revel template?

Incorporating slideshow / carousel into custom tumblr theme

Got a very particular problem here:
I've been developing a tumblr-hosted site locally, using the API to pull in posts without having to copy and paste the project into tumblr a million times. I decided I liked the API better and would just use that in production, but now that it's time to deploy I realize that I have to go back to the custom theme, {block:Posts} method.
I have the post feeding into a Cycle2 slideshow, with 3 slides containing 3 posts each for a total of 9 playlists viewable without going back to the archive. This method works perfectly with the api, but is getting messed up in the custom theme. Here's my current code:
<div class="cycle-slideshow">
{block:Posts}
{block:Text}
<div class="slide-wrapper">
<div class="post">
{block:Post1}
{block:Title}<h2>{Title}</h2>{/block:Title}
<div class="blog_item">
{Body}
</div>
{/block:Post1}
</div>
<!--two more posts before end of slide... -->
</div>
{/block:Text}
{/block:Posts}
</div> <!--end of slide wrapper - 2 more of these before end of slideshow div..
I also tried scrapping the post numbers, but still no dice. In tumblr's docs, they say that
Example: {block:Post5}I'm the fifth post!{/block:Post5} will only be rendered on the fifth post being displayed.
I'm wondering if "being displayed" refers to the html visibility of the post, and if so, if that's interfering with the cycle plugin? The results are one ill-formatted post per slide, and then after cycling through 2 blank slides, the next oldest post takes its place. I'll be pleasantly surprised if anybody has ever had a similar problem but I would kill for some advice. Here's the development site for reference (and the second carousel is working because it's still hooked up to the api). thanks!!
Generally speaking, the following code is what you'd want to have 3 slideshows with 3 posts each.
Note that in the Additional Settings on the Customize screen, you'd have to set the post count to 9 per page in order for this to work properly. I wrapped it in an Index Page block, otherwise this is going to look nasty on a Permalink Page.
{block:IndexPage}
{block:Posts}
{block:Post1}<div class="cycle-slideshow">{/block:Post1}
{block:Post4}<div class="cycle-slideshow">{/block:Post4}
{block:Post7}<div class="cycle-slideshow">{/block:Post7}
<div class="slide-wrapper">
{block:Text}
<div class="post">
{block:Title}<h2>{Title}</h2>{/block:Title}
<div class="blog_item">
{Body}
</div>
</div>
{/block:Text}
{block:Photo}
...
{/block:Photo}
...
</div>
{block:Post3}</div>{/block:Post3}
{block:Post6}</div>{/block:Post6}
{block:Post9}</div>{/block:Post9}
{/block:Posts}
{/block:IndexPage}
However, if you're wanting 3 slideshows with the post types split between the slideshows, the code would look more like the following.
Note that in this scenario, if you were to have 4 texts posts out of 9, all 4 text posts would end up in the Text slideshow. You'd have to use Javascript or CSS to remove or hide the additional posts if you're very strict about your 3.
{block:IndexPage}
<div class="cycle-slideshow">
{block:Posts}
{block:Text}
<div class="slide-wrapper">
<div class="post">
{block:Title}<h2>{Title}</h2>{/block:Title}
<div class="blog_item">
{Body}
</div>
</div>
</div>
{/block:Text}
{/block:Posts}
</div>
<div class="cycle-slideshow">
{block:Posts}
{block:Photo}
<div class="slide-wrapper">
...
</div>
{/block:Photo}
{/block:Posts}
</div>
{/block:IndexPage}
If you need me to clarify anything, let me know.

Managing a list in umbraco 5

I have recently started working on an umbraco 5 project and am finding it a bit of a struggle compared with umbraco 4. What I am trying to do is have a list of items that are managed in the content section of the site where users can add items to a list, this list is then used in drop downs and page categories throughout the site.
I am looking for the best way to do this, I am currently part way through creating a property editor that manages a list of text boxes but not sure if this is the best way of doing it, and Im currently not entirely sure of how to go about doing even this. I can save one property no problem, but a dynamic list?
Can anybody give me some idea of how they would go about doing this with some code examples, theres not a huge amount of resources for 5 out there at the minute.
Many thanks to those who contribute.
UPDATE
I have now copied the multiple textstring property editor from the source code and am looking to update it to have an extra text input. Its using the knockout javascript library of which Im not too familar with, below is the code I have so far, does anyone know how I would update this to save both text values to the database?
<ul class="relatedlinks-textstring-inputs" data-bind="template: { name: 'textstringRow', foreach: textstrings }"></ul>
<script id="textstringRow" type="text/html">
<li style='width: 250px;'>Name<input type="text" data-bind="value: value" />Url<input type="text" data-bind="value: value" /></li>
</script>
#Html.HiddenFor(x => Model.Value, new Dictionary<string, object> { { "data-bind", "value: value" } })