How can you dynamically build router-links in Vue.js? - javascript

I am trying to do the following in Vue.js
<table>
<tr v-for="item in messages">
<td><router-link to="'/user/' + item.id">{{ item.name }}</router-link></td>
</tr>
</table>
My messages property has an array of objects in it. Each object has an id property, which I want to be appended on to my to attribute. So if I had two items in the messages array with ids of 1 and 2, I would expect to get something like this:
<table>
<tr v-for="item in messages">
<td><router-link to="/user/1">{{ item.name }}</router-link></td>
</tr>
<tr v-for="item in messages">
<td><router-link to="/user/2">{{ item.name }}</router-link></td>
</tr>
</table>
I also tried putting doing {{ message.id }}, but that gives me an interpolation error. How can I get this to render the actual value for message.id in the "to" attribute? The item.name attribute renders as expected.

Just add v-bind: before to
<table>
<tr v-for="item in messages">
<td><router-link v-bind:to="'/user/' + item.id">{{ item.name }}</router-link></td>
</tr>
</table>
Without v-bind: you're literally using 'user' + item.id as value.
For more clarification check this docs section

Related

How to bind an object to HTML table in Vue.js, where its properties are dynamically created?

I am using vue.js library for front-end development.
I came a cross a scenario where my JavaScript method returns a list, which has objects, object's number of properties can change each time after method execution.
example my list can contain these type of objects in 2 different executions.
var obj = {
Name : "John",
2020-Jan: 1,
2020-Jul: 2
}var obj = {
Name: "John",
2020-Jan: 1,
2020-Jul: 2,
2021-Jan: 3,
2021-Jul: 4
}
Since Property name is dynamically changes is there any way to bind to HTML ?
<div >
<table>
<thead>
<tr>
<th v-for ="row in Result.Headers">
{{row}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item in Result.Data ">
<td>
{{item.2020-Jan}} // Because don't know the number of properties until run time
</td> // No of <td/>'s can change on no of properties.
<td> // exactly don't know how many <td>'s needed there.
{{item.2020-Jul}}
</td> <td>
{{item.2021-Jan}}
</td>
</tr>
</tbody>
</table>
</div>
Is there way to bind these type of object to fronted in vue.js ?
You need to loop over the item's keys again. This will show all the values in the object
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="(value, key, index) in item">
{{value}}
</td>
</tr>
</tbody>
If you want to filter some of them, for instance check that the keys are valid dates you need to add a v-if and use Date.parse to check for this.
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="(value, key, index) in item" v-if="Date.parse(key) !== NaN">
{{value}}
</td>
</tr>
</tbody>
if u wana show all attr-> u can use this:
<ul v-for="item in Result ">
<li v-for="(value,key,index) in item">{{value}}</li>
</ul>
if u wana show all days u can use v-if and compute to complete youself fillter
<div id="app">
<ul v-for="item in Result" >
<li v-for="(value,key,index) in item" v-if="canShow(key)"> index:{{index}}------ key: {{key}} ------ value:{{value}} </li>
</ul>
</div>
<script>
var vue=new Vue({
el:'#app',
data:{
Result:[{
name: 'SkyManss',
2020-Jan: 1,
2020-Jul: 2
},{
name: 'SkyManss2',
2020-Jan: 1,
2020-Jul: 2,
2021-Jan: 3,
2021-Jul: 4
}]
},
computed:{
canShow(){
return function(skey){
return skey.indexOf('-') > -1;
}
}
}
});
</script>
after some research and some of your suggestions I came up with an answer.
<div>
<table>
<thead>
<tr>
<th v-for ="row in Result.Headers">
{{row}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="row in Result.Headers">
{{item[row]}}
</td>
</tr>
</tbody>
</table>
</div>
Javascript code
this.Result.Headers = Object.keys(result.data[0]);
this.Result.Data = result.data;
But this code only worked for the first time. second time data didn't get updated. So I updated JavaScript code to following code.
Vue.set(self.Result, 'Headers', []);
Vue.set(self.Result, 'Result', []);
this.Result.Headers = Object.keys(result.data[0]);
this.Result.Data = result.data;
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. That I got to know from following post.
vue.js is not updating the DOM after updating the array
Thank You All !!!

Empty header row is being added while using header slot in v-data-table

Empty row is being added while using header slot in v-data-table from vuetify2
Here's the codepen:
https://codepen.io/satishvarada/pen/rNBjMjE?editors=1010
Vue.component('pivot-table',{
data:()=>({
pivotData:[["2018",1470,1436,1445,0],["2019",1953,1824,0,0]],
pivotHeaders:[[{"value":"Month","colspan":1},{"value":"JAN","colspan":2},{"value":"FEB","colspan":2}],[{"value":"Year","colspan":1},{"value":"Count1","colspan":1},{"value":"Count2","colspan":1},{"value":"Count1","colspan":1},{"value":"Count2","colspan":1}]],
}),
template:
`<v-data-table disable-sort disable-filtering :headers="pivotHeaders" :items="pivotData">
<template v-slot:header="{ props: { headers } }"><thead class="v-data-table-header">
<tr v-for="header in headers" style="background-color:yellow;">
<th v-for="head in header" :colspan="head.colspan">{{head.value}}</th>
</tr></thead>
</template>
<template v-slot:body="{ items }">
<tbody>
<tr v-for="item_row in items"><template v-for="item in item_row">
<td>{{ item }}</td></template>
</tr></tbody></template></v-data-table>`
})
Unexpected row is added below the header. The number of cells in this empty row is as same the number of rows present in the header.
I think the issue is related to you data structure since v-data-table accepts arrays of objects as props not an array of arrays, but your use case could be achieved using v-simple-table component in as follows :
<v-simple-table>
<thead>
<tr v-for="header in pivotHeaders" style="background-color:yellow;">
<th v-for="head in header" :colspan="head.colspan">{{head.value}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item_row in pivotData">
<td v-for="item in item_row">{{ item }}</td>
</tr>
</tbody>
</v-simple-table>

how to set title in a for-loop using vue.js in this example?

<template v-for="item in job">
<tr>
<td v-for="i in item.stage" :style="getStyle(i.status.name)" title="[[ i.node.name ]]" >
<b>[[ i.node.name ]]</b>
</td>
</tr>
</template>
I am trying to set the title for each td - but instead the title is literally being set to [[ i.node.name ]] as string rather than the value.
note: [[ i.node.name ]] prints the value so I know it is correct, I must be using wrong syntax for the title though.
also side note: I'm using [[ ]] as delimiters in vue.js
You need to remove the brackets from your title and add a colon : in front of the title. Take a look at https://v2.vuejs.org/v2/guide/syntax.html#Attributes
<template v-for="item in job">
<tr>
<td v-for="i in item.stage" :style="getStyle(i.status.name)" :title="i.node.name" >
<b>[[ i.node.name ]]</b>
</td>
</tr>
</template>

nested ng-repeat that one depend on the other

I have an issue with angular, I want to use two nested ng-repeat in a data table where the first get the data, and the second get the name of field to be retrieved from the data (retrieved in the first ng-repeat)
here is what I tried to do with code :
<table md-table flex-order-gt-sm >
<thead md-head>
<tr md-row >
//1st : get the name of fields, not a problem
<th md-column ng-repeat="field in fields">{{item.name}}</th>
</tr>
</thead>
<tbody md-body>
<tr md-row ng-repeat="item in items">
<td md-cell ng-repeat="field in fields" >
//here is the problem I want to get the item that it's field name is field
{{item.{{field}} }}</td>
</tr>
</tbody>
</table>
for example if fields contain :{'a','b','c'}
and items contains {'a':'1','b':'2','c':'3'};
I want for example for the 1st iteration of {{item.{{field}} }} to return 1
Use toString() to retrieve the scope data in an scope object.
<tr md-row ng-repeat="item in items">
<td md-cell ng-repeat="field in fields" >
{{item[field.toString()]}}
</td>
</tr>
Here is the plunker
As an alternative you could also use a filter:
<td md-cell ng-repeat="field in fields | filter: { name: 'field' }">
</td>
You need to get fields collection according to item of items collection after
getFieldsByItem(item)
Then you can get field from fields collection
{{field}}

Searching through JSON Object with ng-class (AngularJS)

I have two JSON objects defined in a controller (NotificationsController). One with all the notifications and another one with only the ID of the newest notifications (last 3 days).
Format of object "notifications": (t_notifications)
[{"0":"1","1":"4","2":"14-APR-16","3":"ALERT 1","ID":"1","ID_USER":"4","DATE":"14-APR-16","NOTIFICATION":"ALERT 1!"},{"0":"2","1":"1","2":"07-APR-16","3":"ALERT 2!","ID":"2","ID_USER":"1","DATE":"07-APR-16","NOTIFICATION":"ALERT 2!"},{"0":"3","1":"1","2":"13-APR-16","3":"ALERT 3!","ID":"3","ID_USER":"1","DATE":"13-APR-16","NOTIFICATION":"ALERT 3!"}]
Format of object "newest notifications": (newest_notifications)
[{"0":"1","ID_NEWNOTIF":"1"},{"0":"3","ID_NEWNOTIF":"3"}]
I'm displaying all the notifications in a view like this:
<div class="panel-body" ng-controller="NotificationsCtrl">
<table datatable="ng" class="row-border hover">
<thead>
<tr>
<th><b>ID</b> </th>
<th><b>ID_USER</b> </th>
<th><b>DATE</b> </th>
<th><b>NOTIFICATION</b> </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="data in t_notifications" ng-class="{selected: data.ID == **TO COMPLETE**>
<td>{{ data.ID }}</td>
<td>{{ data.ID_USER }}</td>
<td>{{ data.DATE }}</td>
<td>{{ data.NOTIFICATION }}</td>
</tr>
</tbody>
</table>
</div>
I would like to know how it is possible to select in my table only the newest notifications - searching through the JSON object newest_notifications - with ng-class?
PS: "selected" is already defined with a blue background color.
Just use a strict filter
... ng-class="{'selected': (newest_notifications | filter : { ID_NEWNOTIF: data.ID } : true).length !== 0 }"
Fiddle - https://jsfiddle.net/dyxf5xqj/
You can use a expression against data.DATE. For example
<tr ng-repeat="data in t_notifications" ng-class="{selected: data.DATE > someDateInThePast}">

Categories