How to loop object data into the table? - angular5

I have following object with columns and data. I want to display the columns value using *ngFor.
SO far I have tried following code:
public productLists;
this.productLists = [];
this.productLists = this.loadProductLists();
html
<tr *ngFor="let column of productLists.columns">
<th scope="col">{{column}}</th>
</tr>
data
columns:
action: "Action"
product_code_clip: "Product Code Clip"
product_name_clip: "Product Name Clip"
year: "Year"
__proto__: Object
data: (15) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

Have you tried to iterate the data array within your columns object?
<tr *ngFor="let column of productLists.columns.data">
<th scope="col">{{column}}</th>
</tr>

Related

Laravel Datatables - Searchable hidden column still requires a table header column?

I have a Laravel index page with yajra datatables of a model of a customer, with tags (one-to-many) flattened into a single column. This all works as expected. Here is my javascript from my index.blade.php
#push('child-scripts')
<script type="text/javascript">
$(function () {
var table = $('.data-table').DataTable({
lengthMenu: [ 10, 25, 50, 75, 100 ],
pageLength: 50,
processing: true,
serverSide: true,
ajax: "{{ route('customer.index') }}",
columns: [
{data: 'title', name: 'title'},
{data: 'field', name: 'field'},
{data: 'people_count', name: 'people_count', searchable: false},
{data: 'contact_count', name: 'contact_count', searchable: false},
{data: 'phone_count', name: 'phone_count', searchable: false},
{data: 'sample', name: 'sample'},
{data: 'tags', name: 'tags'},
{data: 'action', name: 'action', orderable: false, searchable: false},
]});
});
</script>
here is the relevent part of my html from the same file
<table class="table data-table table-auto strange">
<thead class="border-b">
<tr>
<th>Name</th>
<th>Field</th>
<th>
<x-fluentui-people-16-o /></th>
<th>
<x-fluentui-contact-card-16-o /></th>
<th>
<x-fluentui-call-16-o /></th>
<th>Sample</th>
<th></th>
<th></th>
</tr>
</thead>
</table>
The tags are verbose and taking too much screen real estate.
I followed the directions here to make them searchable but not visible.
laravel yajratable - hide column but make it searchable
{data: 'tags', name: 'tags', visible: false},
Adding visible: false did the trick, I can search for tags and get results.
Question
All of this breaks, the moment I remove ` <th></th> ` from the html. I must have 8 `<th>` elements even though I only have 7 visible columns. What is going on?
OK, this is a little embarrassing. I went back to add titles to my header columns to make them a little more clear.
<th>Sample</th>
<th>Tags</th>
<th>Action</th>
</tr>
</thead>
</table>
Only to discover that the Tag header cell for the corresponding column was gone; datatables had hidden it too. I left it off it off because I presumed that it would just get in the way. I have wasted so much time on this already, but I hope this will be a help to someone else.
TL;DR
Datatables proactively removes the header cell for the corresponding column; you must add it so datatables can hide it.

Vue: How can I get the true array instead of [__ob__: Observer] arrays?

I am new to Vue, and want to get my data from the database with an API call:
data() {
return {
total: 0,
liblist: []
}
}
created() {
this.getLibList();
},
methods: {
async getLibList() {
const { data:res } = await this.$http.get('/api/user/select_all_info');
this.liblist = JSON.parse(JSON.stringify(res));
console.log(res);
console.log(this.liblist);
}
}
Here I want to access the array from my API and then assign the array to liblist:[].
I even tried to use JSON.parse(JSON.stringify(res)) to convert data type.
But sadly I got this result from console like this:
Here is console result of 'res':
(5) [{…}, {…}, {…}, {…}, {…}]
0: {id: "1111", em: "111111", pw: "7"}
1: {id: "12121212", em: "4144#gmail.com", pw: "6666"}
2: {id: "121213333", em: "admin333", pw: "333"}
3: {id: "2222", em: "2222", pw: "2"}
4: {id: "444444", em: "4444", pw: "444"}
length: 5
__proto__: Array(0)
But when it turns to 'liblist',it returns:
(5) [{…}, {…}, {…}, {…}, {…}, __ob__: Observer]
0: {__ob__: Observer}
1: {__ob__: Observer}
2: {__ob__: Observer}
3: {__ob__: Observer}
4: {__ob__: Observer}
length: 5
__ob__: Observer {value: Array(5), dep: Dep, vmCount: 0}
__proto__: Array
I really cannot understand: why after this.liblist = JSON.parse(JSON.stringify(res))the data become 'observer' type ??
In that case I cannot see any data in my table-componet:
my page's display
P.S. Here's my frontend code:
<el-table stripe max-height="500" :data="liblist">
<el-table-column label="Account" prop="id"></el-table-column>
<el-table-column label="Email" prop="em"></el-table-column>
<el-table-column label="Password" prop="pw"></el-table-column>
So what's wrong with my code? Please help me.

VUEJS Display nested object in <b-table> VUE-BOOTSTRAP

I have an array of objects (users) gotten by an api request. Its structure is something like this:
api response: (5) [{…}, {…}, {…}, {…}, {…}]
Inside this array, the objects are like this:
0: {
user_address_string: ('Street 1')
id: (3)
avatar: (img')
...
user: {
id: 1
first_name: 'Lucas'
last_name: 'Smith'
}
},
1: {...},
2: {...},
....
]
It is just a sample just to show you the structure.
As you can see, among its properties there's another object named user{}.
I need to display only the properties contained in this object.
I would like to keep the structure of the table I was using before I got this new api (which didn't have objects as properties).
<b-table
responsive
v-if="users && users.length > 0"
:fields="fields"
:items="users"
>
The template should be something like this:
<template slot-scope="data">
{{ data.item.user }}
</template>
data.item should be the single user in the users array of objects, and with .user I should be able to access the properties of its object property user. (Going further data.item.user.first_name, etc, to access the single properties in it). What am I missing?
Nothing is rendered on the screen.
No errors in the console though.
In the script I have:
users: [],
fields: [
{ key: 'id', label: 'ID'},
{ key: 'name', label: 'Name' }
]
So, how should I write the template for displaying the nested object’s properties?
Also, the directive v-if="users && users.length > 0" in the b-table should still work, right? It is still an array, but of objects this time. Please correct me if I am wrong.
Thank you
You can specify nested field keys in dotted notation:
export default {
data() {
return {
users: [],
fields: [
{ key: 'id', label: 'ID'},
{ key: 'user.first_name', label: 'First Name' },
{ key: 'user.last_name', label: 'Last Name' }
]
}
}
As #Troy Morehouse suggested, I just needed to redefine the fields definition as
{ key: 'user.first_name', label: 'First name' }
**UPDATE after #artworkjpm comment:
The HTML code should be something like this:
<b-table
v-if="users && users.length > 0 && !isLoading"
id="table-transition-userList"
:key="users.id"
responsive
:tbody-tr-class="userStatus"
:tbody-transition-props="transProps"
:fields="fields"
:items="users"
>
<template
v-slot:cell(fullName)="data"
>
{{ data.item.user.first_name }} {{ data.item.user.last_name }}
</template>
<template
v-slot:cell(buttons)="data"
>
<b-button
v-b-tooltip.hover
title="See plan"
class="btn-plan p2"
variant="primary"
:disabled="!data.item.user.is_active"
#click.prevent="seePlan(data.item), selectUser(data.item)"
>
<span class="svg-container">
<svg-icon icon-class="route" />
</span>
</b-button>
</template>
</b-table>
**Minor change in fields, but the concept is the same:
fields: [
{ key: 'fullName', label: 'User' },
{ key: 'buttons', label: 'Operations' }
],
Hope it helps.
xx
Whereever you get your data, you can extract the property you want and save locally in this case it would look something like this:
data()
return {
users: []
}
methods: {
async getUsersFromApi(){
const { data: {users }} = await axios.get(...)
users.map(user => {
this.users.push(user.user)
}
An easy way to do it is by using a formatter in fields definition:
data() {
return {
fields: [
{
key: "avg_score",
label: this.$t("avgScore"),
sortable: true,
sortByFormatted: true,
formatter: (value, key, item) => item.stats.avg_score?.text
},
],
items: [...your item list]
}
}
And in the template:
<b-table :items="items" :fields="fields"></b-table>
The formatter will print the specified key or value automatically.

click and change events are not working for Angular 6 Datatables Responsive extension

I use Angular 6 datatables for show data in the frontend. I used responsive extension to show more data as described in
https://l-lin.github.io/angular-datatables/#/extensions/responsive
<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="row-border hover">
<thead>
<tr>
<th>Category Name</th>
<th>Description</th>
<th>Is Enable</th>
<th>Sub Categories</th>
<th>update</th>
<th>delete</th>
<th>Extra Data</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of vehicleCategoryData; let i = index">
<td>{{data.categoryName}}</td>
<td>{{data.description}}</td>
<td>{{data.isEnable}}</td>
<td>{{data.subCategory.length}}</td>
<td><i class="fa fa-edit" (click)="update(i)"></i></td>
<td><i class="fa fa-trash-o" (click)="delete(i)"></i></td>
<td>{{data.extraData}}
</tbody>
</table>
also my dtOptions are defined as follows.
dtOptions: any = {
pagingType: 'full_numbers',
pageLength: 5,
columns: [{
title: 'Category Name',
data: 'categoryName'
}, {
title: 'Description',
data: 'description'
}, {
title: 'Is Enable',
data: 'isEnable'
},{
title: 'Sub Categories',
data: 'sub'
},
{
title: 'update',
data: 'up'
},
{
title: 'delete',
data: 'del'
},
{
title : 'Extra Data',
data : 'sc',
className : 'none'
}],
responsive: true
};
So everything works fine. but
(click)="update(i)"
(click)="delete(i)"
events are not working. How can i solve this problem. Any suggestions?
I solve this problem by using the listHiddenNodes function.
First i imported the Responsive variable in the component
import Responsive from 'datatables.net-responsive';
then i put this code on the dtOptions
this.dtOptions = {
responsive: {
details: {
renderer: Responsive.renderer.listHiddenNodes()
}
},
};
That's all!

How to manipulate data in vuejs

I'm building a small application using vuejs where I'm calling a url to get some data. I need to manipulate the data before showing it. In the response I'm receiving an array of elements which has fields
client_name: "ABCD Company"
event_type: 3
type: "meeting"
venue: "Mumbai"
with_client: 1
Additionally I have a data set of event_type that looks like this:
events: [
{value: 1, label: "One-on-One meeting"},
{value: 2, label: "Group meeting"},
{value: 3, label: "Broker Roadshow"},
{value: 4, label: "Broker Conference"},
{value: 5, label: "Site Visit"},
{value: 6, label: "Only Management Meet"},
{value: 7, label: "Only IR Meeting"}
],
and with_client is true or false.
So basically my final data will look like something like this:
client_name: "ABCD Company",
event_type: "Broker Roadshow",
type: "meeting",
venue: "Mumbai",
with_client: "yes"
Currently I'm have a v-for loop that looks like this:
<tr v-for="(item, index) in meeting_data">
<td class="text-center">{{ index+1 }}</td>
<td class="text-center">{{ item.client_names }}</td>
<td class="text-center">{{ item.type }}</td>
<td class="text-center">{{ item.event_type }}</td>
<td class="text-center">{{ item.with_client }}</td>
<td class="text-center">{{ item.schedule }}</td>
<td class="text-center"><router-link :to="{name: 'interaction-update', params: {id: item.id}}"><i class="fa fa-pencil-square-o text-navy"></i></router-link></td>
<td class="text-center"><a #click.prevent="deleteInteraction(item.id)"><i class="fa fa-trash-o text-navy"></i></a></td>
</tr>
Use a computed.
This assumes your meeting_data is an array of objects. If it's an object as you suggest in your comment, then show us an example and I'll update the answer.
computed:{
formattedData(){
if (!this.meeting_data) return []
return this.meeting_data.map(d => {
return {
client_name: d.client_name,
type: d.type,
// this find could blow up if the event_type doesn't exist
event_type: this.events.find(e => e.value == d.event_type).label,
with_client: d.with_client ? "yes" : "no",
venue: d.venue
}
})
}
},
Iterate over the formatted data.
<tr v-for="(item, index) in formattedData">
Example.
Based on your pen, it would look something like this:
computed: {
tableFilter: function () {
// Do the filter
let interactions = this.model.interactions
if(this.model.interactions)
{
interactions = this.model.interactions.filter((item) =>
item.client_names.includes(this.search_by_name)
&& item.event_type.includes(this.search_by_event_type));
}
if (!interactions.length > 0) return []
// Return formatted data
return this.interactions.map(d => {
return {
client_name: d.client_name,
type: d.type,
// this find could blow up if the event_type doesn't exist
event_type: this.events.find(e => e.value == d.event_type).label,
with_client: d.with_client ? "yes" : "no",
venue: d.venue
}
})
}
}
That's obviously not a working example but gives you the structure.