separating v-if and v-for Vue.js 3 - javascript

I have read that we shouldn't put v-if and v-for together in vuejs. I've also got an error in the IDE. How am I suppose to separate the v-if and v-for in my code so that it follows the style guide?
<div
v-for="(value, key, index) in items"
v-if="value.level === undefined || value.level < level"
:key="key"
>
level is a computed value too
computed: {
level() {
return (
user.access>3
);
}
},

You can use invisible wrapper (<template>) element with v-if. Benefit of using this is template won't render until condition met. You can read more about template here
Example:
<div v-for="(value, key, index) in items" :key="key">
<template v-if="value.level === undefined || value.level < level"> // It won't render until v-if = true
....

put the v-if directive in a virtual element template :
<div v-for="(value, key, index) in items" :key="key">
<template v-if="value.level === undefined || value.level < level">
....

If you don't want a bunch of empty divs on the dom, filter it.
computed: {
filtered_items: function() {
return this.items.filter(v => typeof v.level === 'undefined' || v.level < this.level)
}
},
Then use filtered_items instead of items in the v-for
Can also do inline:
v-for="item in items.filter(v => typeof v.level === 'undefined' || v.level < level)"

Related

Render class conditionally in React

I'm trying to render a class conditionally. If the mapped item is blank, I'd like there to be a class that renders. Otherwise, no changes. I'm sure this very simple but I'm new at this and not sure how to identify the blank item. Is this a problem with scope? This is the code in my component:
const TableBody = (props) => {
let classes = ''
classes += (props.data.map === '') ? '' : 'collapse'
return (
<tbody>
{props.data.map((item, index) => (
<tr key={typy(item, 'sys.id').safeString || index}>
{props.columns.map(column =>
<td className={classes} role='cell' key={column.label}>{typy(item, column.path).safeObject}</td>)
}
</tr>
))}
</tbody>
)
}
All of the <td> elements are collapsed so the code I'm using above must not be properly detecting a blank value. Can anyone point me in the right direction here?
Per my comment, props.data appears to be an array. You are checking to see if props.data.map === '', which will always evaluate to false. You should probably fix that statement, otherwise the class will always be 'collapse'. Hope that helps!

How to efficiently display text instead of null when binding in vue.js?

In the following code site can be null, but if it is there, then company will not be null. How can I efficiently display a "-" when the site is null that scales well for 1000's of these rows?
<tr v-for="obj in objs" :key="obj.id">
<td>{{obj.site.company.name || "-"}}</td> <!-- does not work -->
</tr>
I can make a method to do this:
methods: {
handleNulls(obj) {
// logic
return "-";
}
}
But it would be nicer if it could be done inline, or using a filter.
I would suggest an inline if. You should check whether site is undefined and whether company is undefined:
<tr v-for="obj in objs" :key="obj.id">
<td>{{obj.site && obj.site.company ? obj.site.company.name : '-'}}</td>
</tr>
Try this :
<tr v-for="obj in objs" :key="obj.id">
<td v-if="obj.site !== null">{{obj.site.company.name}}</td>
<td v-else>-</td>
</tr>
Documentation - conditional rendering
You wanted to show "-" if the site is not available so I did this : (the first element of the array is null)
let app;
function appInit(){
app = new Vue({
el:'#app',
data:{
obj:[
null,
{site:{company:{name:"test2"}}},
{site:{company:{name:"test3"}}}
]
}
});
}
appInit();
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in obj">{{item && item.site && item.site.company&& item.site.company.name ? item.site.company.name : " - "}}
</li>
<ul>
<div>

Vue various product search

I have a bit of code that searches for:
name
category
tag
area
It's okay but I have an issue with searching for a favourite.
Name, category, tag and area are search this function:
return this.meals.filter(meal => {
return meal.strMeal.toLowerCase().includes(this.search.toLowerCase())
&& (category === "All" || meal.strCategory === category)
&& (area === "All" || meal.strArea === area)
&& (tag === "All" || String(meal.strTags).includes(tag))
})
This is how I render my loop:
<li v-for="meal of filteredList">
I have 2 modals, but this modal has to work on click. For example, I click on a product, search only on this product. How can I connect this to filteredList?
The correct syntax is IN not of.
<li v-for="meal in filteredList">
Think of it like this, it's a for loop. It loops through all of the items in the array. So, for each item IN the array.
You could look at it like this:
<li v-for="item in array">
If you need to access the index of these items you can also do this:
<li v-for="(item, index) in array" :key="index">

Why Props data passing between Parent to Child not working in VueJS?

Here, i use some list of data in Javascript variable to pass to VueJs Template Loop.
My Javascript Variable,
var templates = {
0:{
'nb':1,
'column':2
},
1:{
'nb':1,
'column':2
}
}
My Parent Template is,
<div v-for="(te,index) in templates" class="row">
<campaign_segment :t_nb="te.nb" :t_column=te.column> </campaign_segment>
</div>
Parent Template's Source,
<template v-if="showTemplate" id="segment_body">
<b>#{{ t_nb }}</b>
<div v-for="a in t_nb">
<block v-if="t_column == 4 || t_column > 4"></block> // <== Child Template,
</div>
</template>
Child Template's Source,
<template id="campaignBlock">
<b>HIT</b>
</template>
My VueJS,
// For Parent Template
Vue.component(
'campaign_segment', {
template: '#segment_body',
props: ['t_nb', 't_column']
});
// For Child Template
Vue.component('block', {
template: '#campaignBlock'
});
In general,
<div v-for="a in t_nb">
<block v-if="t_column == 4 || t_column > 4"></block> // <== Child Template,
</div>
No loop were generated.
here, if i use,
<div v-for="a in 2">
<block v-if="t_column == 4 || t_column > 4"></block> // <== Child Template,
</div>
Loop is working fine.
Whats wrongs with this, why vuejs never uses the same instance to process the loop ?
What I see is, there can be two issees:
Having multiple components under template, so you can put all of them in a single div, as is solved here.
Using parseInt in v-for, as it can be passed as a string in props instead of an integer, you can also put data type of props as explained here.
HTML
<template>
<div v-if="showTemplate" id="segment_body">
<b>#{{ t_nb }}</b>
<div v-for="a in parseInt(t_nb)">
<block v-if="t_column == 4 || t_column > 4"></block> // <== Child Template,
</div>
</div>
</template>

AngularJS - HTML data binding UI issue

I am binding following in my HTML.
<div>{{user.address[0].addressline1}}, {{user.address[0].addressline2}}, {{user.address[0].city}}, {{user.address[0].state}}, {{user.address[0].zipcode}}</div>
The issue is if addressline1 is null, it unnecessarily shows the , at first.
And also some other fields can be null
So How to display comma only if the value is not null?
Or as a matter of style, you can use a turnery operator to check for the value then format it
{{ !!user.address[0].addressline1 ? user.address[0].addressline1 + ', ' : ''}}
This could be made as filter to be more intuitive
angular.module('myapp', []).filter('trailIfTrue', [function(){
return function(val, trail){
return !!val ? val + trail : '';
}
}]);
usage:
{{ user.address[0].addressline1 | trailIfTrue:',' }}
here is a plunker
User separate span and ng-show so the span will be shown only if user.address[0].addressline1 is not null
<span ng-show="user.address[0].addressline1">{{user.address[0].addressline1}},</span>
<span ng-show="user.address[0].addressline2">{{user.address[0]. addressline2}},</span>
<span ng-show="user.address[0].city">{{user.address[0].city}},</span>
//...
You can use any expression into ng-show Eg:
user.address[0].addressline1 != null
myObj.myIntAttr > 0 && < 10
myObj.myBoolAttr == false
//...

Categories

Resources