METEOR JS. A variable in each loop - javascript

HTML
<template name="contact">
...
{{> FORMULAIRE descrip =descripFormContact }}
...
</template>
<template name="FORMULAIRE" >
<form id={{descrip.idForm}} >
<fieldset id="idFieldSet{{descrip.idForm}}">
{{#each descrip.champs}}
<span id="idSpanLabel{{descrip.idForm}}" ....>{{this.label}}</span>
...
{{/each}}
</fieldset>
</form>
</template>
JS
Template.contact.helpers({
descripFormContact: {
idForm: 'formContact',
champs: [{
nomChp: 'prenom', label: 'Prenom : ', type: 'text', oblig:true,
}]
}
})
All is OK but I can't seem to find the value of "descrip.idForm" in the loop "each".
Can someone tell me why, in the loop "each", "descrip.idForm" is empty, then that the outside of the loop is equal to "formContact"
Thank you for your answer
YC

Could you remove the space between descript and = in your FORMULAIRE template call.
Regs,yann

Related

Render a checkbox and check it based on the existence of a value from a dataset to another dataset

My idea is to checked whether a value exists from a dataset to another dataset. In this case I would like to use the id property.
I'm try handlebars.js , But the following is invalid.
spot_categories array
{spot_categories:[{category:1},{category:2},{category:3},{category:4},{category:5},{category:6}]}
data array
{data:[{spot_category_id:1},{spot_category_id:3}]}
vue.js code
<!-- if have var -->
{{# var ok = false}}
<!-- one for -->
<li v-for="(category,j) in spot_categories">
<label>
<!-- two for -->
<template v-for="(val, l) in data">
<!-- if -->
<template v-if="val.spot_category_id == category.id">
{{ ok = true }}
</template>
</template>
<!-- if ok = true , show value -->
<input :value="category.id" :checked="ok">
</label>
</li>
How can I do? Please help me. thanks!
You are looking at looping once only in your template using your spot_categories dataset and then calling a method to evaluate if its id exists on another dataset. I use v-if and v-else to decide which checkbox element to render. Then I implement array.some() on my evaluation method which is the most fitting in this scenario (you can use a manual for loop but it's too lengthy and generally not recommended if you want a clean-looking code).
new Vue({
el: categoryContainers,
data: {
spot_categories: [
{id: 1},
{id: 2}
],
data: [
{spot_category_id: 1},
{spot_category_id: 3}
]
},
methods: {
checkIfExists: function(item1){
return this.data.some(function(val){ return val.spot_category_id == item1.id });
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="categoryContainers">
<ul>
<li v-for="(category,j) in spot_categories">
<label>
<input type="checkbox" v-if="checkIfExists(category)" :value="category.id" checked>
<input type="checkbox" v-else :value="category.id">
{{ 'Category ID ' + category.id }}
</label>
</li>
</ul>
</div>

Vuejs v-for on inline elements trims whitespace

When looping over an array (or object) with v-for on an inline element, vuejs does not render whitespace around said element.
For example, I have this html:
<div id="app">
Vue Rendering<br>
<a v-for="fruit in fruits" v-bind:href="fruit.url" v-html="fruit.label"></a>
</div>
<div>
Navite rendering<br>
Apple
Banana
Peach
</div>
and this javascript:
var fruits = [
{
label: 'Apple',
url: 'apple.html'
},
{
label: 'Banana',
url: 'banana.html'
},
{
label: 'Peach',
url: 'peach.html'
}
];
var app = new Vue({
el: '#app',
data: {
fruits: fruits
}
});
When Vue renders this, it deletes the spaces between the links. See this jsfiddle.
How can I counter this behaviour ?
From the Docs on List Rendering > v-for on a <template>
Similar to template v-if, you can also use a <template> tag with v-for to render a block of multiple elements. For example:
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
So in order to get sibling elements (and yeah, a breaking space character would count as one), you'll have to add the loop to a parent <template> container and then include any elements / spacing you want in the looped contents like this:
<template v-for="fruit in fruits" >
<span>{{fruit}}</span>
</template>
As of Vue 2.x+, templates trim any breaking space characters, even if they are escaped.
Instead, you can add a slot or text interpolation like this:
<template v-for="fruit in fruits" >
<span>{{fruit}}</span><slot> </slot>
</template>
<template v-for="fruit in fruits" >
<span>{{fruit}}</span>{{ ' ' }}
</template>
If you only want spaces in-between elements, you can output the space conditionally:
<template v-for="(fruit, i) in fruits" >
<span>{{fruit}}</span>{{ i < fruits.length -1 ? ', ': '' }}
</template>
Demo in Stack Snippets
var app = new Vue({
el: '#app',
data: {
fruits: ["apple", "banana", "carrot"]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.0/vue.js"></script>
<div id="app">
<template v-for="(fruit, i) in fruits" >
<span>{{fruit}}</span>{{ i < fruits.length -1 ? ', ': '' }}
</template>
</div>
Further Reading:
Issue #1841 - Suggestion: v-glue / v-for element joins
I had a case where I needed to wrap each character (including spaces) of a string in a <span> and solved it this way.
<template v-for="(letter, i) in 'My text with spaces'">
<span v-if="letter !== ' '">{{ letter }}</span>
<span v-else> </span>
</template>
You can use CSS:
<a v-for="fruit in fruits" v-bind:href="fruit.url" v-html="fruit.label"
style="margin-right: 5px;"></a>

Console warning: component lists rendered with v-for should have explicit keys

I got a problem here, I don't know what is wrong in my code, but I got a warning in my console, how can I remove this warning?
[Vue tip]: <todo-item v-for="todoItem in todos">: component lists rendered with v-for should have explicit keys. See https://v2.vuejs.org/v2/guide/list.html#key for more info.
(found in <Root>)
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue Tutorial</title>
<link rel="shortcut icon" href="https://vuejs.org/images/logo.png">
<script src="scripts/vue.js"></script>
</head>
<body>
<section id="app">
<p>{{ msg }}</p>
<p v-bind:title="message">
Hover your mouse over me for a few seconds to see my dynamically bound title!
</p>
<div>
<p v-if="seen">This text will show or hide if the button was clicked.</p>
<button type="button" v-on:click="isSeen">{{ isSeenText }}</button>
</div>
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
<p>Total count: {{ todos.length }}</p>
<div v-bind:title="reverseMessageText">
<p>{{ reverseMessageText }}</p>
<button v-on:click="reverseMessage">Reverse Message</button>
</div>
<div>
<p>Data binding: <strong>{{ nameOfUser }}</strong></p>
<input type="text" v-model="nameOfUser">
</div>
<div>
<ol>
<todo-item v-for="todoItem in todos" v-bind:data="todoItem"></todo-item>
</ol>
</div>
</section>
<script src="scripts/app.js"></script>
</body>
</html>
app.js
var appComponent = Vue.component('todo-item', {
template: '<li>id: {{ data.id }}<br>text: {{ data.text }}</li>',
props: [
'data'
]
});
new Vue({
el: '#app',
data: {
msg: 'Hello World!',
message: 'You loaded this page on ' + new Date(),
seen: true,
isSeenText: 'Now you don\'t',
todos: [
{
text: 'Learn JavaScript'
},
{
text: 'Learn Vue'
},
{
text: 'Build something awesome'
}
],
reverseMessageText: 'Hello World from Vue.js!',
nameOfUser: 'John Rey'
},
methods: {
reverseMessage: function() {
this.reverseMessageText = this.reverseMessageText.split('').reverse().join('');
},
isSeen: function() {
this.seen = !this.seen;
this.isSeenText = this.seen ? 'Now you don\'t' : 'Now you see me';
}
}
});
console.log
Here is the link that Vue suggested here. I think i don't have any error, I want to solve that warning but I cannot find where's the cause, btw I'm newbie here to Vue.
The answer is listed explicitly in the documentation you linked...
<todo-item v-for="todoItem in todos"
v-bind:data="todoItem"
v-bind:key="todoItem.text"></todo-item>
To summarise some information from the comments below... you use :key to let the component know how to identify individual elements. This allows it to keep track of changes for Vue's reactivity.
It's best to try and bind the :key to some uniquely identifying property of each item. For example, an id.
My solution to a similar problem looked like this:
- <el-radio v-for="option in field.options"> ...
+ <el-radio v-for="(option, index) in field.options" :key="index"> ...
Or using v-bind syntax for index:
+ <el-radio v-for="(option, index) in field.options" v-bind:key="index"> ...
You can use any field of your data as a key. In addition you can use the default id. Furthermore you can define a "key" in your data as in the code below:
Vue.component('task-list', {
template: `
<div><slot>
<task v-for="task in tasks" :key="task.key"> {{task.description}}</task>
</slot></div>
`,
data () {
return {
tasks: [
{description:"Go to market", completed:false, key:"asd"},
{description:"Wake up ", completed:true, key:"rty"},
{description:"Sleep", completed:false, key:"terw"},
{description:"Have breakfast", completed:true, key:"jdr"},
]
};
},
});
Vue.component('task', {
template: `<li><slot></slot></li>`
});
In the place of the key in the task.key you can put one of the field names including the hidden id.

Issue on Passing param to Template as Variable in Html Using Vue JS

I use Vue js to implement template system, its completely dynamic.
So i need to pass attributes and variables to template and each template has different values.
I done on passing attributes, but issue on passing value of a variable.
Here,
My HTML :
<div v-for="product in productsList">
<block v-if="column == 4 || column > 4"
:listAlign="showList ? 'left' : 'center'"
:product_name = product.name
:showAction="showAction"
:block_class="showList ? 'col-md-12 col-sm-12 col-xs-12' : 'col-md-3 col-sm-6 col-xs-6'">
</block>
</div>
Here, i have to pass the value of 1. product_name, 2. product_price, 3. showAction
Also the Class and Align attributes are passed successfully.
My Template :
<template v-if="showTemplate" id="campaignBlock">
<div :class="block_class" :align="listAlign">
<p>#{{ product_name }}</p>
<p>Price : #{{ product_price }}</p>
<input v-show="showAction" type="button" #click="alt()" class="btn btn-default
" value="Action">
</div>
</template>
My VueJS :
Vue.component('block', {
template: '#campaignBlock',
props: ['block_class', 'align', 'listAlign','showAction', 'product_name','product_name'],
data: function () {
return {
n: 0,
nb: 1,
column: 2,
showPrice: false,
showAction: true,
showList: false,
listAlign: 'left'
}
}
});
I only having trouble with passing variables to template.
Is this concept is possible ?
Or any other solution for this issue ?
Thanks in Advance.
What exactly error you are getting. I have corrected few mistakes, check below:
<template>
<div v-if="showTemplate" id="campaignBlock">
<div :class="{'col-md-12' : block_class_var}" :align="listAlign">
<p>{{ product_name }}</p>
<p>Price : {{ product_price }}</p>
<input v-show="showAction" type="button" #click="alt()" class="btn btn-default
" value="Action">
</div>
</div>
</template>
Here is the documentation of using dynamic class in vueJs.

for each item in array {{display item}}

I am trying to access the array values in my code so that I can use them but I am not sure how to. Thanks
var footerButtons = ['NO', 'EXTRA', 'YES'];
<template name="footer">
{{#each footerButtons}}
<h1>
<button class="col-xs-2 mainMenu" type="button">{{what should go here?}}</button>
</h1>
{{/each}}
</template>
You could define your footerButtons helper as follows -
Template.footer.helpers({
footerButtons() {
return [{text: 'NO'}, {text: 'EXTRA'}, {text: 'YES'}];
}
});
Then in your template, you can access the values as shown below.
<template name="footer">
{{#each footerButtons}}
<h1> <button class="col-xs-2 mainMenu" type="button">{{text}}</button> </h1>
{{/each}}
</template>
{{.}} or {{this}} is what you're looking for. This refers to the current object/element in an array.

Categories