Angular Table: Object Data shows in one row - javascript

I am trying to create a table where the input is a Type object. I have managed to return the data in the table however there are currently two issues:
The Value of the Data doesn't match the column
All the values are in one row (i.e Success, Success, Success)
I understand that I should use some mapping logic however, I can't seem to get my head round that. Any help will be greatly appreciated, thanks
.ts
searchValue: string = "3";
logList: any = [];
getLogs() {
const numOfLogs = new FormData();
numOfLogs.append('n_log', this.searchValue)
this.fileUploadService.getLogs(numOfLogs).subscribe(
data => {this.logList = data},
);
}
html
<table class="table table-striped" style="width:1000px;table-layout:fixed;font-size:10px;color:black;">
<thead>
<tr>
<th>Name</th>
<th>Date</th>
<th>FilePath</th>
<th>Updated</th>
</tr>
</thead>
<tbody>
<tr>
<td *ngFor="let item of logList | keyvalue"">{{ item.value}}</td>
</tr>
</tbody>
</table>
console.log(this.logList)
{
"Name": [
"name1",
"name2",
"name3"
],
"Date": [
"2021-12-13",
"2021-12-12",
"2021-12-11"
],
"FilePath": [
"FileName1.xlsx",
"FileName2.xlsx",
"FileName3.xlsx",
],
"Updated": [
"2021-12-31T00:00:00",
"2021-12-31T00:00:00",
"2021-12-31T00:00:00",
],
}

You're telling it to repeat over each key so:
<td *ngFor="let item of logList | keyvalue">{{ item.value}}</td>
Would become:
<tr>
<td>{{ logList.Name }}</td>
<td>{{ logList.Date }}</td>
<td>{{ logList.FilePath }}</td>
<td>{{ logList.Updated }}</td>
</tr>
Which would then be interpolated as:
<tr>
<td>name1,name2,name3</td>
<td>...etc</td>
</tr>
I'm guessing what you want is:
<tr>
<td>name1</td>
<td>2021-12-13</td>
<td>FileName1.xlsx</td>
<td>2021-12-31T00:00:00</td>
</tr>
<tr>
<td>name2</td>
<td>2021-12-12</td>
<td>FileName2.xlsx</td>
<td>2021-12-31T00:00:00</td>
</tr>
...etc
The easiest thing would be to parse your data into a different type. So your data would look then like this
[
{
"Name": "name1",
"Date": "2021-12-13",
"FilePath": "FileName1.xlsx",
"Updated": "2021-12-31T00:00:00",
},
...
]
Then your html would look like this instead:
<tr *ngFor="log in logList"> <!-- notice the ngFor is now on the row -->
<td>{{ log.Name }}</td>
<td>{{ log.Date }}</td>
<td>{{ log.FilePath }}</td>
<td>{{ log.Updated }}</td>
</tr>
If you're unable to modify the data coming back to look like that, you'd have to parse it on your own:
...
this.fileUploadService.getLogs(numOfLogs).subscribe(data => {
this.logList = [];
for(var x = 0; x < data.Name.length; x++){
this.logList.push({
Name: data.Name[x],
Date: data.Date[x],
FilePath: data.FilePath[x],
Updated: data.Updated[x],
});
}
});

Related

Is there a way of displaying the value of an object inside an array?

I'm building a component on my project, which is actually getting all the data and console logging it, but here's the problem: Inside my array of clients, i have some objects (address, documents, ...), and i can't manage to call them on my table.
My script:
<script>
export default {
data: () => ({
clients: [],
}),
methods: {
getClients() {
this.$api
.get("/api_v1/clientes", {
})
.then((response) => {
this.clients = response.data[0];
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
},
mounted() {
this.getClients();
},
};
</script>
My table (inside ):
<tbody>
<tr v-for="client in clients" v-bind:key="client.id">
<td>{{ client.id }}</td>
<td>{{ client.name }}</td>
<td>{{ client.email }}</td>
<td>{{ client.documents.cpf || client.documents.cnpj }}</td>
<td>{{ client.documents.celular }}</td>
<td>{{ client.status }}</td>
<td v-if="client.address">
{{ `${client.address.localidade} / ${client.address.uf}` }}
</td>
<td v-else>-</td>
<td>
<a :href="`/see-client/${client.id}`"
><i class="icon-magnifier"></i
></a>
<i class="icon-check" style="color: green"></i>
<i class="icon-close" style="color: red"></i>
</td>
</tr>
</tbody>
My controller:
public function index(Request $request)
{
$data = [
'pag' => 'All clients',
'link' => '/'
];
return view('clients.index', $data);
}
The data:
Someone have a clue of a different approach i could have? I'm using Vue2. It's one of my first big projects, so previously sorry for any rookie mistake. Thanks for your time and help!
This line is only getting the first client:
this.clients = response.data[0];
response.data is your array of clients (from the looks of things). When you use .data[0], you're getting the first element of the array (i.e. the first client).
Then, this line is trying to loop over 1 client, not an array of clients.
<tr v-for="client in clients" v-bind:key="client.id">
Try changing
this.clients = response.data[0];
to
this.clients = response.data;
If that doesn't work (it looks like you've got a weird data structure), try this instead:
this.clients = response.data.data;
Or this (it's unclear to me how many nested data properties you have):
this.clients = response.data.data.data;
I just made a quick analysis about your code. I think you should polish it a little bit.
Let me start with a quick catch up:
Update yuor js section with:
<script>
export default {
// Please do use the function format instead of lambda expression, it's recommended in the vue2 docs.
data() {
return {
clients: [],
};
},
methods: {
// Change this to an async method, so you can have more control on your code.
async getClients() {
try {
/**
* Here, you should have to know, that your file `routes/api.php` hass all of the prefixed /api routes
* So you have a direct access to /api prefixed routes
* Additionally read a little bit about destructuring.
*/
const response = await this.$api.get("/api/clientes");
// Now, please notice that you have 2 data path names.
this.clients = response.data.data; // {or please follow the correct path to the array container of the clients}.
} catch (e) {
console.log("Check this error: ", e);
}
},
},
// Now, change your mounted to an async method
async mounted() {
// Trust me this is going to work perfectly.
await this.getClients();
},
};
</script>
Now, please, please change your api controller logic to a response()->json(...)
public function index(Request $request)
{
// Your retrieve logic...
return response()->json($data);
}
Finally if you have successfully configured everything abouve, your vue component should be able to retrieve the information correctly, and your tbody must work this way...
<tbody>
<tr v-for="client in clients" v-bind:key="client.id">
<td>{{ client.id }}</td>
<td>{{ client.name }}</td>
<td>{{ client.email }}</td>
<td>{{ client.documents.cpf || client.documents.cnpj }}</td>
<td>{{ client.documents.celular }}</td>
<td>{{ client.status }}</td>
<td v-if="client.address">
<!-- You can replace what you have with: -->
{{ client.address.localidade }} / {{ client.address.uf }}
</td>
<td v-else>
-
</td>
<td>
<a :href="`/see-client/${client.id}`">
<i class="icon-magnifier"></i>
</a>
<i class="icon-check" style="color: green"></i>
<i class="icon-close" style="color: red"></i>
</td>
</tr>
</tbody>

how to pass json data into query string and use that data in another page

Here table contains book details which contains book name, author, pric, ISBN and category. When user click on Book Name it should pass the data to another page using querystring
<script type="text/javascript" src="book.js">
<body ng-app="mymodule" >
<div ng-controller="myController" >
<table border=2>
<thead>
<tr>
<th>ISBN</th>
<th>NAME</th>
<th>AUTHOR</th>
<th>CATEGORY</th>
<th>PRICE</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="book in books">
<td>{{ book.ISBN }}</td>
<td >{{ book.Name }}</td>
<td>{{ book.Author }}</td>
<td>{{ book.Category }}</td>
<td>{{ book.price }}</td>
</tr>
</tbody>
</table>
books.js
var myapp = angular.module('mymodule', []);
myapp.controller("myController", function($scope, $http,$window) {
$http.get("https://api.myjson.com/bins/p4ujn").then(function(response) {
$scope.books = response.data;
$scope.getdetail=function(){
$scope.getbookdetail=this.book;
$window.location.href = "orderpage.html";
}
});
});
orderpage.html
<script type="text/javascript" src="book.js"></script>
<body ng-app="mymodule" >
<div ng-controller="myController" >
{{getbookdetail.Name}}<br>
{{getbookdetail.Author}}
{{getbookdetail.price }}<br>
</div>
</body
So you said this: 'When user click on Book Name it should pass the data to another page using querystring'
Querystring is not the best method to use for something like this. You're better off learning about ui-router and setting up routes that handle this. You have your initial state, then you can create another state to display each book. Something like this:
.state('initial', {
url: 'some/initial',
template: 'some/initial/template.html',
params: {
name: null,
price: null,
author: null,
isbn: null,
category: null
}
})
.state('read-book-details', {
parent: 'initial',
url: 'some/url',
template: 'some/template.html',
params: {
name: null,
price: null,
author: null,
isbn: null,
category: null
}
})
Then when you're transitioning from one 'state' to another, you do it like so passing along the parameters you want:
$state.go('read-book-details',
{ name: book.name, price: book.price, author: book.author });
On the 'other' page's controller (ie the controller for the 'read-book-details' state) you can inject $state and get the parameters that are passed in via $state.params (ie., $state.params.price)
A second option for you is to have a service that you can store the data in, then retrieve from anywhere else. This obviously becomes useful when you start to pass around larger amounts of data rather than simpler smaller pieces (like name, price).

Concat 2 datas from json Angular ng-repeat

I try to put data from another array into one part in table.
My first json "names" :
[
{
"name": "AAAAAA",
"down": "False"
},
{
"name": "BBBBBB",
"down": "True"
},
{
"name": "CCCCC",
"down": "False"
}
]
Second json "data" :
[
{
"data": "35%"
}
]
Javascript:
var app = angular.module('app', []);
app.service('service', function($http, $q){
this.getNames = function () {
var names = $http.get('names.json', {cache: false});
var datas = $http.get('data.json', {cache: false});
return $q.all({datas,names});
};
});
app.controller('FirstCtrl', function($scope, service, $http) {
var promise = service.getNames();
promise.then(function (data) {
$scope.names = data.names.data;
$scope.datas = data.datas.data;
$scope.namesanddata = $scope.names.concat($scope.datas);
console.log($scope.namesplit);
console.log($scope.datas);
});
});
Table in HTML :
div ng-controller="FirstCtrl"
<table>
<tbody>
<tr ng-repeat="name in namesanddata">
<td>{{name.name}}</td>
<td ng-if="name.down=== 'False'">{{name.down}}</td>
<td ng-if="name.down !== 'False'">{{name.data}}</td>
</tr>
</tbody>
</table>
</div>
My problem - <td ng-if="name.down !== 'False'">{{name.data}}</td>dont show in table. in console.log it concat to array like 4 object and probably by this it don't show in table next to {{name.name}}, but i don't know how to show {{name.data}} from another json in table instead {{name.down}}.
Thanks for answers in advance.
To give you an output of:
AAAAAA False
BBBBBB 35%
CCCCC False
Remove this line from the Controller:
$scope.namesanddata = $scope.names.concat($scope.datas);
Then either:
Solution 1 - Inline in the view
Change your ng-repeat as follows:
<tr ng-repeat="name in names">
<td>{{ name.name }}</td>
<td>{{ (name.down === 'False') ? name.down : datas[0].data }}</td>
</tr>
OR
Solution 2 - Keep the view clean by using a Filter
app.filter('myFilter', function () {
return function(items, datas) {
var filtered = [];
angular.forEach(items, function (i) {
if (i.down !== "False")
i.down = datas[0].data;
filtered.push(i);
});
return filtered;
}
});
Change your ng-repeat as follows:
<tr ng-repeat="name in names | myFilter: datas">
<td>{{ name.name }}</td>
<td>{{ name.down }}</td>
</tr>

Rendering a table with dynamic headers

I have to render a table with dynamic headers, I mean, I don't want to do something like this in the HTML
<table>
<tr>
// THIS TABLE ROW IS WHAT I SAY
<th>here info</th>
<th>something here</th>
<th>another header</th>
</tr>
<tr ng-repeat="thing in things">
<td>{{thing.asfs}}</td>
<td>{{thing.asx}}</td>
<td>{{person.dsf}}</td>
</tr>
</table>
I want something like this
<table>
<tr ng-repeat="head in heads">
{{head}}
</tr>
<tr ng-repeat="bar in bars">
<td ng-repeat="foo in foos"></td>
</tr>
</table>
that is only an example, I need to do it with this data:
{
"55f6de98f0a50c25f7be4db0":{
"clicks":{
"total":144,
"real":1
},
"conversions":{
"total":4,
"amount":229
},
"cost":{
"cpc":0.1999999999999995,
"ecpc":1145.0000000000027,
"total":28.79999999999993
},
"revenue":{
"total":4,
"epc":0.027777777777777776
},
"net":{
"roi":-1.1612903225806457,
"total":4
},
"name":"Traffic Source #2",
},
"55f6de98f0a50c25f7be4dbOTHER":{
"clicks":{
"total":144,
"real":1
},
"conversions":{
"total":4,
"amount":229
},
"cost":{
"cpc":0.1999999999999995,
"ecpc":1145.0000000000027,
"total":28.79999999999993
},
"revenue":{
"total":4,
"epc":0.027777777777777776
},
"net":{
"roi":-1.1612903225806457,
"total":4
}
"name":"Traffic Source #3"
},
}
every key, like clicks, conversions, cost, etc, should be a td, it is just that I don't want static HTML.
Any suggestions?
EDIT
And also, sometimes that object will grow, could come up with some more keys like this one 55f6de98f0a50c25f7be4db0
I did this fiddle with the exact same data I am receiving
http://jsfiddle.net/wLkz45qj/
UPDATE:
What you need to do is first convert you inconvenient object to array of objects with simple structure, and then use my code , i.e.
{
a: {
b:{
c: 'x'
}
}
}
will turn into
[[ a, { 'b.c' : 'x' }], ...]
or just
[{ _id : a , 'b.c' :'x'}, ...]
easiest way to do that is to use lodash or underscore ( check map, flatMap, pairs etc)
#jperezov showed you core idea, little bit detailed example:
$scope.peopleKeys = Object.keys(people[0])
and
<table>
<tr>
<th></th>
<th ng-repeat="personKey in peopleKeys">
{{ personKey }}
</th>
</tr>
<tr ng-repeat='p in people'>
<th>{{ $index }}</th>
<td ng-repeat="personKey in peopleKeys">
{{ p[personKey] }}
</td>
</tr>
</table>
You may also have some dictionary with display names:
$scope.displayNames = {
id: 'ID',
firstName: 'First Name'
...
}
and then your header going to be:
<tr>
<th></th>
<th ng-repeat="personKey in peopleKeys">
{{ displayNames[personKey] }}
</th>
</tr>
PS: OR you can just use ui-grid
var app = angular.module('myApp', []);
function PeopleCtrl($scope, $http) {
$scope.headers=[];
$scope.data = [];
$scope.LoadMyJson = function() {
for (var s in myJson){
$scope.data.push(s);
if ($scope.headers.length < 1)
for (var prop in myJson[s]){
prop.data = [];
$scope.headers.push({th:prop, td: []});
}
}
for (var s in $scope.data){
for (var prop in $scope.headers){
var header = $scope.headers[prop].th;
var data = myJson[$scope.data[s]][header];
$scope.headers[prop].td.push(data);
}
}
};
}
What you're looking for is something like this, I think:
http://jsfiddle.net/wLkz45qj/8/
Maybe iterate another time over "inner" for formatting.

How I can extract object from JSON result usinig angularJS

I use this function de read data from a web service
$scope.getProduitByCatID = function () {
$http.get("/getProduitByCategorieID?id=" + $scope.categorie.id).success(function (data) {
$scope.produits = data;
});
};
the value in my model $scope.produits is :
{
"reference": 1,
"designation": "sony",
"prix": 5100,
"categorie": {
"id": 1,
"nom": "serveur"
}
}
I want to show this result with an ng-repeat
<tr ng-repeat="p in produits">
<td>{{p.reference}}</td>
<td>{{p.designation}}</td>
<td>{{p.prix}}</td>
</tr>
but it's not work
I want to extract just this information in my model :
{
"reference": 1,
"designation": "sony",
"prix": 5100
}
because I have two entities product(id,designation,prix) and categorie(id,nom) in association ManytoOne how I can do that using angularJS?
$scope.produits has to be an array. And every time you receive new data, you push it into this array:
$scope.produits = [];
$scope.getProduitByCatID = function () {
$http.get("/getProduitByCategorieID?id=" + $scope.categorie.id)
.then(function successCb(res) {
$scope.produits.push(res.data);
}, function errorCb() {
})
;
};
Or you create a new array every time you receive new data:
$scope.getProduitByCatID = function () {
$http.get("/getProduitByCategorieID?id=" + $scope.categorie.id)
.then(function successCb(res) {
$scope.produits = [res.data];
}, function errorCb() {
})
;
};
Or you can even create an array in ngRepeat:
<tr ng-repeat="p in [produits]">
You can do like this
Declare array scope $scope.produits=[].
$scope.getProduitByCatID=function(){
$http.get("/getProduitByCategorieID?id="+$scope.categorie.id)
.success(function(data){
$scope.produits.push(data) ;
});
};
Create then html from produits array.
<tr ng-repeat="p in produits">
<td>{{p.reference}}</td>
<td>{{p.designation}}</td>
<td>{{p.prix}}</td>
<td valign="top">
<table>
<tr ng-repeat="c in p.categorie">
<td>{{c.id}}</td>
<td>{{c.nom}}</td>
</tr>
</table>
</td>
</tr>
Since you said you have a JSON string, you can use
$scope.produits=JSON.parse(data) to get the Object from the JSON string. As
the others said, to use it in ngRepeat, it has to be an array:
Example without ng-repeat
$http.get("/getProduitByCategorieID?id="+$scope.categorie.id)
.success(function(data){
$scope.produits=JSON.parse(data);
});
Then:
<tr">
<td>{{produits.reference}}</td>
<td>{{produits.designation}}</td>
<td>{{produits.prix}}</td>
</tr>
To use ng-repeat, your JSON string needs to be like this:
[{"reference":1,"designation":"sony","prix":5100.0,"categorie":{"id":1,"nom":"serveur"}}]
But you don't need it, to get just reference, destignation and prix
As your data is an object:
{
"reference": 1,
"designation": "sony",
"prix": 5100,
"categorie": {
"id": 1,
"nom": "serveur"
}
}
You can show it in the view, by this way:
<table border="1">
<tbody>
<tr>
<td>{{produits.reference}}</td>
<td>{{produits.designation}}</td>
<td>{{produits.prix}}</td>
</tr>
<!-- To show categorie data. -->
<tr>
<td colspan="3">
<table border="1">
<thead>
<tr>
<td colspan="2">categorie</td>
</tr>
</thead>
<tbody>
<tr>
<td>id:</td>
<td>{{produits.categorie.id}}</td>
</tr>
<tr>
<td>nom:</td>
<td>{{produits.categorie.nom}}</td>
</tr>
</tbody>
</table>
</td>
</tr>
<!-- End to show categorie data. -->
</tbody>
</table>

Categories

Resources