Get value from array data in Vue - javascript

I'm kinda new to Vue and i'm struggling to get one value from an array. I'm making an axios get request where I return an array of users containing the values (name, display_name, role, and few others fields). I'm able to get all these values and mount my table with the component below:
<template>
<div class="container">
<table class="mt-3 table roboto table-stripped table-hover table-sm">
<thead class="thead-light">
<th>Name</th>
<th>Username</th>
<th>Profile</th>
<th class="text-center">Is manager</th>
</thead>
<tbody v-for="user in users">
<td v-text="user.name"></td>
<td v-text="user.username"></td>
<td v-text="user.display_name"></td>
<td class="text-center">
<button
class="letter-shadow btn-sm font-500 grey-darkest roboto letter-spacing"
:class="showRole">Activate
</button>
</td>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
users: [],
}
},
computed: {
showRole() {
// wanted to diff button colors here
}
},
mounted() {
axios.get('/api/users').then(response => this.users = response.data);
},
}
</script>
So I wanted to modify that class showRole depending on the value of user.display_name, if the user.display_name is equal to "Manager" e.g. I would show a btn-danger. I just don't know how can I get this value to compare, if I try to use this.user.display_name on showRole method I get nothing (undefined). Thanks for any help.

I think you should use a method instead, as you can't pass parameters to computed properties.
Use this
...
methods : {
showRole(user){
//code that returns the button class
}
}
...
<button :class="showRole(user)">Activate

Related

How to get the value of a specific row in a table in vuejs?

How can I get the value of a specific row in a table in VueJS 2?
This is my table right now
Below is my code to generate a table and two buttons that will show a modals; one is to edit detail and the other is to show the QR Code coming from the database. I want to get the last value of the loop and put it in SHOW QR Button and the Show QR Button will contain the last value from the loop.
<div class="myTable table-responsive">
<table class="table">
<thead class="thead-dark">
<tr>
<th>Member ID</th>
<th>First Name</th>
<th>Middle Name</th>
<th>Last Name</th>
<th>Address</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="result in filteredList" :key="result.id">
<td>{{result.Memb_ID}}</td>
<th>{{result.First_Name}}</th>
<th>{{result.Middle_Name}}</th>
<th>{{result.Last_Name}}</th>
<th>{{result.Address}}</th>
<div class="row justify-content-center">
<b-button v-b-modal.showDetails size="lg" class="showDetails" variant="danger">Edit</b-button>
<b-button v-b-modal.modalQR size="lg" class="showQR" variant="success">Show QR</b-button>
</div>
</tr>
</tbody>
</table>
</div>
This is my modal where I want to have different QR for every user to be inserted.
Below is my modal for the Show QR Button
<b-modal id="modalQR" title="Generated Details">
<div class="showQR text-center">
<qrcode-vue :value="results.url" :size="size" level="H"></qrcode-vue>
</div>
</b-modal>
and below is my script
<script>
import QrcodeVue from "qrcode.vue";
import axios from "axios";
export default {
data() {
return {
search: "",
results: {},
value: "",
size: 200,
selected: [],
};
},
computed: {
filteredList() {
return this.results.filter(post =>
post.First_Name.toLowerCase().includes(this.search.toLowerCase())
);
}
},
methods: {
getUsers() {
axios
.get("localhost:9000/user/")
.then(response => (this.results = response.data))
.catch(error => console.log(error.message));
}
},
components: {
QrcodeVue
},
mounted() {
this.getUsers();
}
};
</script>
v-for also gives you the index of the item you're on:
<tr v-for="(result, index) in filteredList" :key="result.id">
Then you can just use index === filteredList.length
You can try this:
<tr v-for="result in filteredList.data" :key="result.id">
<td>{{result.Memb_ID}}</td>

Vue.js Data binding issue

I am trying to bind data in my userDetails array through post request but i did not get the data , i had tried all the possible solution given in stackoverflow and also in vue.js docs but nothing helps me here is my code.
ND.user_list = new Vue({
el: '#user_list',
data: {
userDetails: []
},
mounted: function () {
$.post(ND.routes['users.get'], [], function(data) {
//console,log(data);
this.$set(this, 'userDetails', data);
//this.usersDetails = data;
}.bind(this), 'json');
//onsole.log(this.userDetailsdata);
}
});
i am getting data in console log in mounted function but not getting in userDetails array declare in data. here is my view code
<div class="ui grid container" id="user_list">
<table class="ui celled padded table">
<thead>
<tr>
<th colspan="6">Top Users</th>
</tr>
</thead>
<thead>
<tr>
<th class="ui center aligned">#</th>
<th class="ui center aligned">Name </th>
<th class="ui center aligned">Email </th>
<th class="ui center aligned">User Type</th>
<th class="ui center aligned">Action </th>
</tr>
</thead>
<tbody>
{% verbatim %}
<tr v-for="user in userDetails">
<td>1</td>
<td class="single line">{{ user.email }}</td>
<td class="ui center aligned "></td>
<td class="ui center aligned "></td>
<td class="ui center aligned ">
<select class="ui dropdown">
<option value=" ">Action </option>
<option value="1">Edit</option>
<option value="0">Delete</option>
</select>
</td>
</tr>
{% endverbatim %}
</tbody>
</table>
</div>
Thanks in advance.
The this in the callback fo $.post() does not refer to the VueJS instance. This means that this.userDetails actually will return undefined within the callback. What you can do is to create a proxy for the VueJS instance as such:
ND.user_list = new Vue({
el: '#user_list',
data: {
userDetails: []
},
mounted: function () {
// Proxy `this`
var that = this;
$.post(ND.routes['users.get'], [], function(data) {
// `that` will refer to VueJS instance
that.userDetails = data;
}, 'json');
}
});
You are using this.$set wrong: it should only be used when you got an object in the data object and want to add properties to that object that wasn't there before, or if you want to change indexes of the array. Then first argument should not be the vue object, but the data object (i.e. the object or array in the data object). See documentation here: https://v2.vuejs.org/v2/guide/reactivity.html or https://v2.vuejs.org/v2/api/#Vue-set.
Instead of: this.$set(this, 'userDetails', data); you should just do this.userDetails = data;. Have you tried this? Also, if you change elements in the array, then you should use Vue.set or splice, but read the documentation carefully before you use it.

How can I retrieve data from an array which is inside another array and display it in the table?

Using Vue.js , I am able to retrieve and display id,description and location, but why in the tasks column I only have [object Object] in all the rows ?!
(tasks is an array inside jobs array)
<template>
<div>
...
<table class="table table-hover">
<thead>
<tr>
<th v-for="column in columns">
...
</th>
</tr>
</thead>
<tbody>
<tr v-for="work in jobs">
<td>{{work["id"]}}</td>
<td>{{work["description"]}}</td>
<td>{{work["location"]}}</td>
<td v-for="tasks in jobs" >{{work["tasks"]}}</td>
</tr>
</tbody>
</table>
<script>
export default{
data : function() {
return{
columns: ['id', 'description', 'location', 'tasks'],
jobs: '',
update: this.getData()
}
},
methods: {
//to get data from the backend API
getData() {
this.$http
.get('http://localhost:3001/api', (data) => {
this.jobs = data["jobs"]
})
}
}
</script>
You are iterating over jobs and not each task inside the job's tasks
You should do something like -
<tr v-for="work in jobs">
<td>{{work["id"]}}</td>
<td>{{work["description"]}}</td>
<td>{{work["location"]}}</td>
<td v-for="task in work.tasks" >{{task["id"]}} -
{{task["description"]}} - {{task["location"]}}</td>
</tr>
Or however you want to display there. But the idea should be to iterate on the tasks array inside each work object
You'll need to explicitly extract the fields that you want to show from tasks. Also, the syntax for the nested v-for would be something like task in work.tasks, so that your task points to each task inside of your tasks array for each work:
<tr v-for="work in jobs">
<td>{{work["id"]}}</td>
<td>{{work["description"]}}</td>
<td>{{work["location"]}}</td>
<td v-for="task in work.tasks">
{{task["id"]}} <br>
{{task["description"]}} <br>
{{task["location"]}}
</td>
</tr>

Populate cells without knowing the data key

My data is an array of objects with key-value pairs. I'm trying to populate a table with the data in a polymer component. If I use the key explicitly, it works. Here is an example with "FacilityId":
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<template is="dom-repeat" items="{{columns}}">
<th>{{item}}</th>
</template>
</tr>
</thead>
<tbody>
<template is="dom-repeat" items="{{data}}">
<tr>
<td>{{item.FacilityId}}</td>
</tr>
</template>
</tbody>
</table>
However, as you can see from the dynamically generated columns, I don't always know what the keys will be named. I tried using {{item[0]}} but that doesn't work, and even if it did I won't know how many there will be. I also tried using a nested template but I couldn't figure it out.
Here is what my data looks like (again, the number and names of fields could vary though):
Based on the answer referenced by #David R, this works:
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<template is="dom-repeat" items="{{columns}}">
<th>{{item}}</th>
</template>
</tr>
</thead>
<tbody>
<template is="dom-repeat" items="{{data}}">
<tr>
<template is="dom-repeat" items="{{_toArray(item)}}">
<td>{{item.value}}</td>
</template>
</tr>
</template>
</tbody>
</table>
And the custom function from https://stackoverflow.com/a/30794220/736893:
Polymer({
is: 'widget-table',
properties: {
data: {
type: Array,
value: function() {return []}
}
},
_toArray: function(obj) {
return Object.keys(obj).map(function(key) {
return {
name: key,
value: obj[key]
};
});
}
});

Smart-table clearing table rows and headers when I close a modal?

I'm using Angular-Smart-table to generate a table full of events for a project.
Adding and removing columns is a requirement, and we have a separate UI component for doing so. This UI component is a modal, and it's a checkbox of the columns I want to include. When this modal closes however, my smart-table goes blank and doesn't update with new choices when I update the table column headers.
Here is the code in the controller that handles the tablesettings event.
function activate(){
vm.$on('tablesettings', function(event, args){
setTimeout(function(){
console.log(args);
vm.tableColumns = {};
angular.forEach(args.columns, function(v,k){
vm.tableColumns[v.value] = v.label;
});
vm.tableRows = [];
addTabletoScope(TableService.cache.data);
},30000)
});
}
function addTabletoScope(td){
vm.tableRows = [].concat(vm.tableData);
console.log(vm.tableColumns);
}
Here is the HTML for the table:
<div class="gTable" style="overflow-x:auto; height:100%;">
<table style="width: 100%" st-table="tableRows" st-safe-src="tableData" st-pipe="tableControl.getPages()" st-pagination-scroll class="table table-striped scroll">
<thead>
<tr>
<th ng-repeat="(key, val) in tableColumns">{{val}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in tableRows">
<td >{{row.eventDateString}}</td>
<td >{{row.cocom}}</td>
<td >{{row.country}}</td>
<td >{{row.province}}</td>
<td >{{row.district}}</td>
<td >{{row.iedType}}</td>
<td >{{row.incidentType}}</td>
<td>{{row.eventId}}</td>
<!-- <td ng-hide="cityremove">{{row.city}}</td>-->
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4" class="text-center">
<div st-pagination="" st-items-by-page="pageNumbers" st-displayed-pages="7"></div>
</td>
</tr>
</tfoot>
</table>
</div>
Here's where I broadcast the tablesettings event,
function handleWidgetSettingsReturn(response) {
switch (response.widgetType) {
case "chart": {
if (!angular.isUndefined(response.widgetSubType) &&
response.widgetSubType !== scope.item.settings.widgetSubType) {
scope.item.settings.widgetSubType = response.widgetSubType;
}
break;
}
case "table": {
if (!angular.isUndefined(response.widgetOptions)) {
$log.info("Table settings set");
scope.item.settings.widgetOptions = response.widgetOptions;
console.log(scope.item.settings.widgetOptions);
scope.$broadcast('tablesettings', scope.item.settings.widgetOptions);
}
}
}
}
This is where the modal instance is closed on ok.
function ok() {
var result = {
widgetType: $scope.widgetConfig.widgetType,
widgetSubType: ($scope.widgetConfig.getWidgetSubtype())? $scope.widgetConfig.getWidgetSubtype() : undefined,
widgetOptions: ($scope.widgetConfig.generateWidgetOptions())? $scope.widgetConfig.generateWidgetOptions() : undefined
};
$modalInstance.close(result);
It feels like my template doesn't come back and isn't refreshing or changing, even when I update the scope.tableColumns with the modal response. $scope.apply() also does not work for me, nor a refresh method.
I'm not sure why my smart-table goes blank when I hit ok for that modal.

Categories

Resources