Expand only one row in the table - html

I have a table with rows, where I list the data from json file.
In one row I'm slicing the data to show only 100 symbols.
I want to display full text when user click on the row. I managed to do it, but It opens all rows. How to do it only for the one row, which clicked?
<tr *ngFor="let lfiexport of lfilist | filter:searchText">
<td (click)="fullViewFlag= !fullViewFlag" class="text-left">
<span *ngIf="fullViewFlag">{{lfiexport.desc}}</span>
<span *ngIf="!fullViewFlag">{{lfiexport.desc | slice:0:100}}</span>
</td>
</tr>

You are using same fullViewFlag multiple times, so it will effect all the rows. So, I suggest you maintain different fullViewFlag properties for each object and can try the below code
Working stackblitz
TS file
export class AppComponent {
name = 'Angular ' + VERSION.major;
lfilist = [{
desc: [1, 2, 3, 4, 5, 6]
}, {
desc: [7, 8, 9, 10, 11, 12]
}, {
desc: [13, 14, 15, 16, 17, 18]
}].map(item => {
return {
...item,
fullViewFlag: false
}
});
}
Template file
<tr *ngFor="let lfiexport of lfilist">
<td (click)="lfiexport.fullViewFlag = !lfiexport.fullViewFlag" class="text-left">
<span>{{lfiexport.fullViewFlag ? lfiexport.desc : lfiexport.desc | slice:0:2}}</span>
</td>
</tr>
No need of *ngIf we can use terinary operator ?:

Related

How to display <td> value based on <th> value

I have three arrays which I have to display in the table. The three arrays are as follows:
let array1 = [
{id: 'p1', name: 'Adam', age: 27},
{id: 'p2', name: 'Jack', age: 20}
{id: 'p3', name: 'Jane', age: 21}
{id: 'p4', name: 'Rock', age: 23}
];
let array2 = [
{id: 'p3', occupation: 'Teacher', marital_status: 'Married'},
{id: 'p4', career: 'Wrestler', hobby: 'Gymming'}
];
let headers = [
{index: 1, name: 'id'},
{index: 2, name: 'name'},
{index: 3, name: 'age'},
{index: 4, name: 'occupation'},
{index: 5, name: 'marital_status'},
{index: 6, name: 'career'},
{index: 7, name: 'hobby'},
];
Now I want to display it inside the table. Here's what I've tried so far.
<table>
<thead>
<tr>
<th *ngFor="let head of headers">{{head?.name}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let person of array1; index as i">
<td>{{ person?.name ? person?.name : '-' }}</td>
<td>{{ person?.id }}</td>
<td>{{ person?.age }}</td>
<ng-container *ngFor="let header of headers">
<td *ngFor="let item of array2">
<ng-container *ngIf="header.name == item[header.name]">{{ item[header.name]}}</ng-container>
</td>
</ng-container>
</tr>
</tbody>
</table>
I want to display the data based on table header's (th) value
I think you're looking for a result like the one in this stackblitz. You needed to connect the ids between your arrays. The solution in this stackblitz is not a good one, however. You shouldn't put methods in your template as they will run an excessive amount due to change detection. I only created it this way to provide an example solution.
What I would recommend is combining array1 and array2 so that all of your elements have the extra fields in one object, instead of referencing two objects that share the same id. This is the simplest and most efficient solution. Alternatively, you could create a pipe that produces the correct result instead of using a method within the template.
create an unique array
//first create an objct with all the elements
const emptyObj=headers.reduce(a:any,b:any)=>({...a,b.name:''))
//then create an object using spread operator
arrayFull=this.array1.map(x=>{
const el=this.array2.find(y=>y.id==x.id)
return {...emptyObj,...x,...el}
})

Passing JSON data to Laravel view without casting in the model

I have this function that fetches data from a table, paginates the data, and passes it to the view:
public function job_requests(){
$orders = DB::table('orders')
->select('id','order_data','order_status')
->paginate(5);
return view('autorepair/mechanics/job_requests',compact('orders'))
->with('i', (request()->input('page', 1) - 1) * 5);
}
The column order_data contains data of the following format:
{
"personal_data": {
"email": "info#info.com",
"telephone_number": "0999",
"postal_address": "LON",
"car_registration": "GB BHG"
},
"inperson_diagnostic": {
"diagnostic_inspection": "67.30",
"car_wont_start_inspection": "67.30",
"plugin_diagnostic_inspection": "67.30"
},
"tyres": {
"front_wheels": 1,
"rear_wheels": 1,
"wheel_width": 45,
"wheel_profile": 1,
"wheel_rim": 1,
"speed_rating": "w",
"final_price": 90
},
"servicing_and_mot": {
"mot_with_collection_delivery": 75,
"major_service": 304.52,
"full_service": 203.45,
"interim_service": "149.70",
"vehicle_health_check": 50
},
"inspection_services": {
"premium_prepurchase_inspection": 146.38,
"standard_prepurchase_inspection": 104,
"basic_prepurchase_inspection": 86.44
},
"repairs": {
"ABS wheel speed sensor replacement": 964,
"ABS pump replacement": 712,
"Brake pedal switch replacement": 568,
"Air conditioning regas (R1234yf Gas ONLY)": 469
}
}
In my view, I have this:
#if(!$orders->isEmpty())
<table class="table table-bordered">
<tr>
<th>No</th>
<th>Order Status</th>
<th>Order Data</th>
<th width="280px">Action</th>
</tr>
#foreach ($orders as $order)
<tr>
<td>{{ ++$i }}</td>
<td>{{ $order->order_status }}</td>
<td>{{ $order->order_data}}</td>
<td>
<a class="btn btn-info" href="{{ url('/view_product/' . $order->id) }}">Show</a>
<a class="btn btn-primary" href="{{ url('/edit_product/' . $order->id ) }}">Accept</a>
</td>
</tr>
#endforeach
</table>
#else
<p>No orders yet.</p>
#endif
{!! $orders->links() !!}
I can display the JSON data here $order->order_data but I would like to have it decoded first. How can I pass a decoded array sent to the view and be able to keep the pagination links?
You could decode it in the view.
Depending on the format of order_data that is actually passed to the view (forgive me, I don't know off-hand how builder or eloquent retrieves jsonb type), but you can use dd() or gettype() in the view, to help identify what data type order_data is when delivered to the view):
If the content comes into the view as a string, try json_decode() on the order_data value. I think you should be able to iterate over the result of that, if that is your intent.

Angular looping values individually

In my component.ts I have something like this
testOptions: SelectItem[] = Object.keys(TestEnum).map(a => {
return { label: this.translate.instant('TestEnum.' + a), value: a };
});
test.enum.ts:
export enum TestEnum {
A = 'A',
B = 'B',
C = 'C',
}
"translate" uses a json file in my case en.json:
"TestEnum": {
"test1": "Test 1",
"test2": "Test 2",
"test3": "Test 3",
my component.html looks like this:
<ng-template #tBody let-row="row">
<td class="iconLinkColumn">
<span *ngIf="!isRowMenuDisabled(row)" class="newton-more" [title]="'common.options' | translate"
style="padding-bottom: 8px;" (click)="toggleRowMenu($event, rowMenu, row)"></span>
</td>
<td>
<span *ngFor="let f of avrFlagOptions">
{{ f.label}}
</span>
</td>
When I start my angular app I am getting displaying all of my json names in each row of my table. How is it possible to loop the values individually, so that in row one appears Test 1 and in row two appears Test 2?
Very sure testOptions is an KeyValue Array and I cannot see a ngFor in your code.
This I believe will do the trick.
Answer:
<si-newton-section>
<cc-scrollable-table>
<ng-template #tBody let-row="row">
<td class="iconLinkColumn" *ngFor="let option of testOptions | keyvalue">
<span *ngIf="!isRowMenuDisabled(row)" class="newton-more" [title]="'common.options' | translate"
style="padding-bottom: 8px;" (click)="toggleRowMenu($event, rowMenu, row)"></span>
<td>{{option.value}}</td>
</ng-template>
</cc-scrollable-table>
</si-newton-section>

How to iterate over values of Map values

I would like to fill of this cells, this is initiall view of my app:
-> during app works for each rider rider's score will be fulfilled in such a way:
I have a .ts file where I put values of rider score (it's a map -> key is heat number, value - score of particular rider) (if it will be both string or number depends on further configuration)
export const guests = {
1: new Racer(9, 'Name_1', new Map([['1', 1], ['4', 2], ['7', 4]])),
2: new Racer(10, 'Name_2', new Map([['1', 3], ['3', 4]])),
3: new Racer(11, 'Name_3', new Map([['2', 3], ['6', 2]])),
4: new Racer(12, 'Name_4', new Map([['6', 3], ['10', 3], ['13', 2]]))
};
I would like to get all values of map values in html, however I'm not able to iterate over values of this map.
Further info: There should be all the time displayed all cells (it is designed that there should be exactly the same at the beginning
We don't know how entries for each racer there will be (probably for each rider this will be different)
<table>
<tbody>
<tr *ngFor="let racer of team; let index = index">
<td>{{racer.number}}</td>
<td>{{racer.name}}</td>
<td *ngIf="racer.places">{{racer.places.values().next().value}}</td>
<td *ngIf="racer.places">{{racer.places.values().next().value}}</td>
<td *ngIf="racer.places">{racer.places.values().next().value}}</td>
<td *ngIf="racer.places">{racer.places.values().next().value}}</td>
<td *ngIf="racer.places">{racer.places.values().next().value}}</td>
</tr>
</tbody>
</table>
expected output
instead of only first entry there should be all values from Map
working repo:
https://stackblitz.com/edit/angular-iterate-over-map-values
The way you are initializing the map doesn't create a map after all. Make the following change to guests:
// now it actually contains key-value pairs
const guests = {
1: new Racer(9, "Name_1", { "1": 1, "4": 2, "7": 4 }),
2: new Racer(10, "Name_2", { "1": 3, "3": 4 }),
3: new Racer(11, "Name_3", { "2": 3, "6": 2 }),
4: new Racer(12, "Name_4", { "6": 3, "10": 3, "13": 2 }),
};
now create a new property in the team object called remaining, this holds an array which contains the extra number of columns that are needed for each row. It is dynamically created for each racer.
team = Object.values(guests).map(racer => {
return {
...racer,
remaining: new Array(5 - Object.values(racer.places).length)
}
});
and on the template, iterate over this newly created array for the remaining <td> that should be empty:
<table>
<tbody>
<tr *ngFor="let racer of team">
<td>{{racer.number}}</td>
<td>{{racer.name}}</td>
<td *ngFor="let heat of racer.places | keyvalue">
{{ heat.value }}
</td>
<td *ngFor="let rem of racer.remaining" style="width: 10px;">
</td>
</tr>
</tbody>
</table>
This is some awful data structure to work with.
Simply loop through the range that you need and check for each cell if the data exists with .has() method. Show the data in a ternary expression with .get() method if it exists, or null if it's missing.
Here is the HTML code that should work with your data structure:
<table>
<thead>
<tr>
<td>No.</td>
<td>Racer</td>
<td *ngFor="let p of [1,2,3,4,5]">{{p}}</td>
<td>Sum</td>
<td *ngFor="let p of [6,7]">{{p}}</td>
<td>Sum</td>
</tr>
</thead>
<tbody>
<tr *ngFor="let racer of team; let index = index">
<td>{{racer.number}}</td>
<td>{{racer.name}}</td>
<td *ngFor="let p of [1,2,3,4,5]">{{racer.places.has(""+p) ? racer.places.get(""+p) : null}}</td>
<td>TODO: Sum</td>
<td *ngFor="let p of [6,7]">{{racer.places.has(""+p) ? racer.places.get(""+p) : null}}</td>
<td>TODO: Sum</td>
</tr>
</tbody>
</table>
Unless you are planning to expand the Racer class, I suggest you switch it to an interface and simply use JSON data structure with Objects instead of a Map

AngularJS table using data from REST API

I want to display a table using AngularJS. The data source for the table will be a REST API. Here is an example response:
{
"value": 43,
"C_class": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13
],
"C_name": [
"C_1",
"C_2",
"C_3",
"C_4",
"C_5",
"C_6",
"C_7",
"C_8",
"C_9",
"C_10",
"C_11",
"C_12",
"C_13"
]
}
I want to display the data in the format below:
<tr><td> 1</td><td>C_1<td>
<td>2<td><td>C_2<td>
<td>3<td><td>C_3<td>
<td>4<td><td>C_4<td>
<td>5<td><td>C_5<td>.....
I have tried using ng-repeat, but unable to fetch. Thank you
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody><tr ng-repeat="value in tests">
<td>{{value.C_name}}</td>
<td>{{value.C_class}}</td>
</tr></tbody></table>
You are not using ng-repeat in correct way. You can take help from the below code to display your table:
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody>
<tr ng-repeat="value in tests.C_class">
<td ng-bind="tests.C_class[$index]"></td>
<td ng-bind="tests.C_name[$index]"></td>
</tr>
</tbody>
</table>
I'll suggest you study a little bit about using ng-repeat.
Try using ng-bind instead of {{}}. see here
This worked for me.
http://plnkr.co/edit/7gLpeyrtyMgnqtdXDxAu?p=preview
<body ng-controller="myCtrl">
<div class="container">
<table class="table table-striped" style="height: 100px; width: 100px;">
<tr ng-repeat="(key,value) in new_c_obj">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
</div>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.response = {
"value": 43,
"C_class": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
"C_name": [ "C_1", "C_2", "C_3", "C_4", "C_5", "C_6", "C_7", "C_8", "C_9", "C_10", "C_11", "C_12", "C_13"]
};
$scope.c_obj = {};
$scope.new_c_obj = {};
$scope.c_obj.c_class = $scope.response["C_class"];
$scope.c_obj.c_name = $scope.response["C_name"];
for($scope.i = 0; $scope.i <= $scope.c_obj.c_class.length-1; $scope.i++){
$scope.new_c_obj[$scope.c_obj.c_class[$scope.i]] = $scope.c_obj.c_name[$scope.i];
}
});
You can use the $index in your ng-repeat (as suggested by B.A.B.U) or properly reformat your data into a new array :
var orgArray = your_data;
var newArray = [];
orgArray.C_class.forEach(function (p, i) {
newArray.push({ C_class: p, C_name: orgArray.C_name[i] });
});
and from there you can apply ng-repeat on the new array to display the fields.
You can simply add those two into another object array..
var mainObjC = array();
C_class.forEach(myFunction);
var x = 0;
function myFunction(){
var obj = {
C_name : C_name[x],
C_class : C_class[x]
}
x++;
mainObjC.push(obj);
}
And your html would be
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody>
<tr ng-repeat="value in mainObjC">
<td>{{value.C_name}}</td>
<td>{{value.C_class}}</td>
</tr>
</tbody>
</table>
The format of the data being returned from your API doesn't lend itself well to what you're trying to achieve. You'd have to make assumptions about the the relationship of data between the two arrays. A better structure would be like this:
[
{
"class": 1,
"name": "C_1"
},
{
"class": 2,
"name": "C_2"
},
{
"class": 3,
"name": "C_3"
},
{
"class": 4,
"name": "C_4"
},
{
"class": 5,
"name": "C_5"
}
]
I've created a fiddle which might help, it uses the above data and displays a table with the data: https://jsfiddle.net/9ypkv77x/