Variables in Handlebars - variables

I'm passing models to a handlebars template and putting a few of the properties in a row. I want to have some sort of position variable for each row. Specifically, I want to know how many rows have been created and have a position associated with each row.
e.g.
{{#each row}}
<span class = (indexHere)>
<tr>
<td> <{{this.property}}>
</tr>
</span>
{{/each}}

This is an old question and maybe at that time Handlebars did not include the #index property, but according to current (1.3.0) documentation:
When looping through items in each, you can optionally reference the current loop index via {{#index}}

You make your own helper :-)
Here's one you can steal:
https://gist.github.com/1048968

Related

Using computed value in v-for (Vue.js)

I'm currently making bitcoin trading web app (personal project. Not a business one)
I have a bunch of cryptocurrencies prices from API, and showing it all by using v-for loop.
here's part of my code:
<tbody class="text-sm">
<tr v-for="coin in props.coins" :key="coin.code" class="hover:bg-zinc-600">
<td class="p-1">
<div class="font-semibold">{{ coin.name }}</div>
<div class="text-xs text-gray-400">{{ coin.code }}</div>
</td>
<td
class="text-right font-bold align-top p-1"
>{{ Number(coin.trade_price).toLocaleString() }}</td>
<td
:class="{ 'text-blue-400': isNegative(coin.signed_change_rate), 'text-red-400': isPositive(coin.signed_change_rate) }"
class="text-right p-1"
>
<div>{{ Number(coin.signed_change_rate).toFixed(2) }}%</div>
<div class="text-xs">{{ coin.signed_change_price }}</div>
</td>
<td class="text-right align-top p-1">{{ convertTp24h(coin.acc_trade_price_24h) }}</td>
<td class="text-right p-1">
<button class="bg-red-700 rounded-lg hover:bg-red-600 p-1">매수</button>
</td>
</tr>
</tbody>
As you can see I have many methods and expressions that converts raw value from API to human-readables.
I'm wondering if this is a bad practice. I heard that methods are called everytime so, rather use computed().
But as you can see I have my values from API in Object(props.coins) and I'm looping this object in v-for. Can I still use computed() methods to convert a value inside an Object that is also looped by v-for?
You can't use computed for items in a loop, since they don't take in arguments. Computed is used for .. computed properties and methods take in arguments e.g. formatChangeRate()
You are right that methods are called everytime, but that's totally fine and normal practice.
So creating a component with methods like formatChangeRate, formatTradePrice is totally fine.
There are ways to make it work with computed properties but in my opinion its not worth it.
1)
You coould make another component that takes in the item as a prop, uses computed property and displays it in componenent's template but that's a total overhead.
2)
You could map the array and reference it by index. Something like:
computed: {
changeRate() {
this.coins.map(coin => {
return Number(coin.signed_change_rate).toFixed(2) + '%'
})
}
}
Now changeRate is an array of formatted change rates so you could in your v-for do something like
v-for="(coin, index) in coins)">
<td>changeRate[index]</td>
So now you're looping through the array multiple times, and the code is less testable and less readable.
In my opinion using methods is totally fine and the right way to go in this example. The performance of calling a simple formatting method multiple times is negligible.
Also the cache you're refering to is that computed properties are cached based on their reactive dependency. E.g. you have in your data, firstName and lastName. You could then make a computed property called fullName that concats those two. The caching would work so that fullName doesn't change unless firstName or lastName changes.
Since you're looping through an array the value that would be computed is always changing.
you are right, methods are called everytime and in theory thats not really good, but in practice if your method just concat strings or other simple operations, that's really not a big deal. Your computer can do millions of operations like that per seconds.
In the other hand if you do complex operations then the solution is to precalculate before.
After you receive your data construct an Array looking something like bellow and use this one in your template
(pseudo code)
[{
name,
code,
changeRate: Number(signed_change_rate).toFixed(2),
...
},
...
]

Aurelia: Using index value to increment array value in input binding

I am trying to increment an array value inside a value.bind directive so that, in this example, three rows are created, incrementing the array number:
<tr repeat.for="i of 3">
<td><input type="text" value.bind="GS.qData.estate[**${$index}**].name"></td>
**strong text**</tr>
I have tried several permutations ( {$i}, etc ), but nothing seems to work.
Further research seems to show that the repeater won't do this, so I have other solutions.
Thanks for the reply.

How to find an item in Selenium WebDriver?

I want to find the following item using Selenium. The value of the class changes whenever there is a change. This is inside a complex page (multiple iframes, and other items loaded dynamically). The only unique id is itemid, which is dynamic value and title combination. If I click on this Action, am getting another new set of complex items. I am new to Selenium. How to do that?
HTML:
<td itemid="xxyyy.as123" title="Actions" nowrap="" class="text-button">Actions <img src="../row.gif"></td>
<td itemid="xxyyy.as123" title="Actions" nowrap="" class="text-button button-active">Actions <img src="../row.gif"></td>
<td itemid="xxyyy.as123" title="Actions" nowrap="" class="text-button button-hover">Actions <img src="../row.gif"></td>
The code I tried:
Find by Xpath
var element=driver.FindElement(By.XPath("html/body/div[id='pageContent']/iframe/#document/ht‌ml/frameset/frame[name='detailsDisplay']/#document/html/body/form[name='tableForm‌']/div[id='divToolbarContainer']/div[id='divToolbar']/div[1][class='toolbar']/tab‌​le/tbody/tr/td[title='Actions']"));
Find by Link Text
var element = driver.FindElement(By.LinkText("Actions"));
Any help would be appreciated.
Try
By.CssSelector("td[title="Actions"]");
By.CssSelector("td[itemid="xxyyy.as123"]");
By.CssSelector("td[itemid="xxyyy.as123"][title="Actions"]")
Create Dynamic CSS Selector.
For Example:
driver.FindElement(By.CssSelector("td[itemid$="xxyyy."]")).Click();
Note: In dynamic Elements, there is always a part of locator wich is fixed. we need to generate the locator using this part.
If fixed part is at starting - Use Carrot Character (^)
If fixed part is at Middle - Use Asterisk sign (*)
If fixed part is at End - Use Doller sign ($)
Finally I was able to achieve it, by using the frame names.
driver.SwitchTo().Frame("content").SwitchTo().Frame("detailsDisplay");
var element = driver.FindElement(By.XPath("//*[#id=\"divToolbar\"]/div[1]/table/tbody/tr/td[1]"));
Thanks everyone.

Looping over two-dimensional array containing objects in Vue.JS

The problem
In Vue, I'm passing an array called issues. The array contains (at present) two objects, but can contain infinite amounts of objects. Every object then has another array named issues, nested inside of it.
The issue is that when I need to display the data, I find that I can't seem to reach the inner "issues" section of it.
I can loop through the first array like so:
<tr v-for="issue in issues" track-by="id">
But that only lets me see the first two objects. I then tried:
<tr v-for="issue in issues" track-by="id">
<td>
<div class="btn-table-align" v-for="issue_title in issue.issues">
#{{ issue_title.title }}
</div>
</td>
</tr>
Which lets me access the sub-elements, but doesn't generate enough rows. I then tried looping over it AGAIN, like so:
<div v-for="first in issues" track-by="id">
<tr v-for="issue in first" track-by="id">
<td>
<div class="btn-table-align">
#{{ issue.id }}
</div>
</td>
</tr>
</div>
But, alas - it generates no rows at all when I do that.
I'd basically need a way to run a "issue in issues", then another for the results and THEIR direct children. The only issue is - I can't figure out how to do it, and Vue won't respond to any of the above attempts! I find a severe lack of documentation on two-dimensional arrays in Vue as well, which has me confused further.
Can anyone shed some light on this? Is it possible, or do I need to adjust the data sent to Vue differently?
To help, I shot an image of an example structure: http://i.imgur.com/6Oz67R9.png
This was a typical 5am question, where I now realize that the data I'm passing makes no sense - it should be the other way around. The actual issues should be in the first array, and the subarray should contain affected servers.

Calculate module of index int Struts2 iterator

I'm using Struts2 iterator to setup a list of checkbox in a table. I want to have 10 checkbox per row, so I'm doing the following:
<table>
<tr>
<s:iterator value="securityMasterFields" status="fieldNameStatus" var="fieldName">
<s:if test="#fieldNameStatus.index % 10 ==0">
</tr><tr>
</s:if>
<td>
<s:checkbox name="fieldsToShow" fieldValue="%{fieldName}" value="%{fieldName}"/>
</td>
</s:iterator>
</tr>
</table>
It never goes through the if, so I'm assuming the mod is not been calculated correctly. How do I do it?
thanks
Well, I had to add some parentheses and it worked correctly. The loop was working, it was just that it wasn't going through the if.
<s:if test="(#fieldNameStatus.index % 8 )==0"></tr><tr></s:if>
It looks good to me. Two thoughts:
1) try printing the result of the test in s:property tag
2) It looks like you will have empty table rows... Are you looking at the generated html or just the output, because if it is just the output then unless you have some CSS giving you some table padding and borders, without an empty 'td' element the row might collapse and make it appear as if nothing is being added. So do make sure you print the empty 'td' elements too!