My requirement is to have dropdowns in each row of two columns of grid as below:
Here is stackblitz for my problem: https://stackblitz.com/edit/angular9-primeng9
User can select values for each row and save. I am able to fetch data from data source using service and initialize dropdown options in subscribe of observable. However, I am not able to set the selected item of each row on page load to display pre-existing rows (I think problem of setting up [(ngModel)]).
Also, I need to add a plus button which would add a new row to this table and result should be saved to database on save action. Any guidance / lead to address this issue would be of great help.
Below is HTML code I am using:
<p-table [columns]="cols" [value]="rows">
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr>
<td>
<p-dropdown [options]="DropdownSource" [(ngModel)]="rowData.AAttribute" placeholder="Select"
[showClear]="true"></p-dropdown>
</td>
<td>
<p-dropdown [options]="DropdownSource" [(ngModel)]="rowData.BAttribute" placeholder="Select"
[showClear]="true"></p-dropdown>
</td>
</tr>
</ng-template>
</p-table>
and in component (subscribe in onchanges):
this.cols = [
{ "field": "field_0", "header": "A Attribute" },
{ "field": "field_1", "header": "B Attribute" }
];
this.rows = [{ "AAttribute": "Data3", "BAttribute": "DataC" },
{ "AAttribute": "Data5", "BAttribute": "DataE" }];
this.DropdownSource= [
{ "AAttribute": "Data1", "BAttribute": "DataA" },
{ "AAttribute": "Data2", "BAttribute": "DataB" },
{ "AAttribute": "Data3", "BAttribute": "DataC" },
{ "AAttribute": "Data4", "BAttribute": "DataD" },
{ "AAttribute": "Data5", "BAttribute": "DataE" },
{ "AAttribute": "Data6", "BAttribute": "DataF" }]
ngmodel expects object from the array.
refer below stackblitz https://stackblitz.com/edit/angular9-primeng9-dgxsjj
this.mappingRows = [{ "targetCol": "DataF", "SourceCol": this.sourceAttributes.find(p=>p.label === "Data3") },
{ "targetCol": this.targetAttributes[3], "SourceCol": "Data6" },
{ "targetCol": "DataC", "SourceCol": "Data1" }];
Related
I have been searching for hours how I can translate the values of an object array with the module ngx-translate,
Here is an extract of my code but I don’t know how to implement the json file
Template HTML :
<div class="sort-header-container">
<table matSort class="mat-sort">
<tr *ngFor="let item of items" class="row">
<td class="row">{{item.critere}}</td>
<td>{{item.res}}</td>
</tr>
</table>
</div>
The object array in the service :
items: any[] = [
{ critere: "Code-modèle", res: "Mizuno Shadow 4" },
{ critere: "Code Libellé", res: "KR32" },
{ critere: "Stock", res: 10 },
{ critere: "Prix TTC", res: "Bleu" },
{ critere: "Couleur", res: 42 },
{ critere: "Matière", res: 125 },
{ critere: "Zone", res: 100 },
];
I need to translate only the critere column
Thank you
You need to use the TranslatePipe from ngx-translate.
<div class="sort-header-container">
<table matSort class="mat-sort">
<tr *ngFor="let item of items" class="row">
<td class="row">{{item.critere | translate}}</td>
<td>{{item.res}}</td>
</tr>
</table>
</div>
Make sure your critere field have the corresponding translations in the json translation files
example for en english translation:
{
"Prix TTC": "Price",
"Couleur": "Color",
}
As taken from the example in ngx-translate github
You can use the translate pipe in your code, like this:
<td class="row">{{ item.critere | translate }}</td>
For this to work, your critere would need to be keys in your language file, for example:
{
'Stock': 'Stock english translation',
'Couleur': 'Is this color?'
}
Thank you very much for your answers
Finally here's what I did :
<tr *ngFor="let item_translate of ('PRODUCT.PRODUCT' | translate); let i = index " class="row"
[ngStyle]="item_translate.critere == 'Stock' && stock<0 ?{color:'red'}:{color:'#474646'}">
<td class="row">{{item_translate.critere}}</td>
<td>{{items[i].res}}</td>
</tr>
In my json example fr :
"PRODUCT": {
"PRODUCT": [
{
"critere": "Code-modèle"
},
{
"critere": "Code Libellé"
},
{
"critere": "Stock"
},
{
"critere": "Prix TTC"
},
{
"critere": "Couleur"
},
{
"critere": "Matière"
},
{
"critere": "Zone"
}
]
}
how to display value data based on index array. here I make a modal edit data, I have a json like the following
[
{
"ID": 3,
"idusers": 3,
"skills": "Go",
"profiency": "Expert",
},
{
"ID": 48,
"skills": "laravel",
"profiency": "laravel",
},
{
"ID": 47,
"skills": "Vue",
"profiency": "Expert",
}
]
table data that I display
<tr v-for="(skill, index) in getSkills" :key="skill.ID">
<td>{{ index + 1 }}</td>
<td>{{ skill.skills }}</td>
<td>{{ skill.profiency }}</td>
<td class="text-xs-center">
<td><div v-if="editBtn == true">
<v-btn class="mr-3" x-small fab v-on:click="handleEdit(item,index)" color="primary"><v-icon>mdi-cancel</v-icon></v-btn>
</td>
</tr>
and this my modal edit
<v-dialog v-model="skillForm" width="500">
<v-container>
<v-text-field outlined dense>
{{profiency}}
</v-text-field>
</v-container>
</v-dialog>
my method
export default {
name: "Skills",
data: function() {
return {
formAddSkills: "",
skillForm: false,
editBtn: "",
skills: {
skills: "",
profiency: "",
},
};
},
computed: {
...mapState({ getSkills: (state) => state.resume.Skills }),
dataSkills() {
return this.skills;
},
},
methods: {
handleEdit(item, index) {
this.skillForm = true;
this.editBtn = true;
this.profiency = item.profiency
// console.log(item)
console.log(index)
},
}
}
the question is how to display data based on ID, when I click the edit button it appears and enters the text field form
Pass skill from your method as a parameter
#click="handleEdit(skill,index)
Then declare a variable, currentObject, and then equate it this.currentObject = skill inside the method.
Then you can access currentObject.id via the v-model binded to your text field.
Below is my JSON object and I am trying to show the same in html table.
$scope.results = {
"data": [
{
"name": "Sam",
"details": [
{
"official": [
{
"address1": "Link road",
"pincode": 76755554
},
{
"address1": "K main road",
"pincode": 9766565
}
]
},
{
"name": "John",
"details": [
{
"official": [
{
"address1": "Old college road",
"pincode": 11111
},
{
"address1": "near east side",
"pincode": 6555446
}
]
}
]
}
]
}
]
}
I have used ng-repeat to achieve the below output. But I am not getting the expected result
This is the code which I have tried and got stuck JSFIDDLE
Any idea on how to achieve my expected result will be really helpful.
You may have to tweak this slightly if your data structure can get more complicated when there are more levels, but this should reformat your data and flatten everything into an array of people without all the different levels.
$scope.peopleFlat = [];
function flattenPeople(people) {
people.forEach((person) => {
$scope.peopleFlat.push({
name: person.name,
addresses: person.details[0].official
});
if (person.details.length > 1) {
flattenPeople([person.details[1]]);
}
});
}
flattenPeople($scope.people);
Then you can use a combination of ng-repeat-start and ng-repeat-end to make it work using rowspan instead of a nested <table> element.
<table class="table table-bordered table-condensed">
<tr>
<th>Name</th>
<th>Address</th>
<th>Pincode</th>
</tr>
<tr ng-repeat-start="person in peopleFlat">
<td rowspan="{{person.addresses.length || 1}}">{{person.name}}</td>
<td>{{person.addresses.length ? person.addresses[0].address1 : ''}}</td>
<td>{{person.addresses.length ? person.addresses[0].pincode : ''}}</td>
</tr>
<tr ng-repeat-end ng-repeat="address in person.addresses.slice(1)">
<td>{{address.address1}}</td>
<td>{{address.pincode}}</td>
</tr>
</table>
I dynamically created an array using rows and columns
[
{
"name": "table 1",
"rows": [
"row 1",
"row 2",
"row 3",
"row 4",
"row 5"
],
"columns": [
"column 1",
"column 2"
],
"col1": [
{
"1": "row1col1"
},
{
"2": "row2col1"
},
{
"3": "row3col1"
},
{
"4": "row4col1"
},
{
"5": "row5col1"
}
],
"col2": [
{
"1": "row1col2"
},
{
"2": "row2col2"
},
{
"3": "row3col2"
},
{
"4": "row4col2"
},
{
"5": "row5col2"
}
]
},
{
"name": "table 2",
"rows": [
"row 1",
"row 2",
],
"columns": [
"column 1",
"column 2",
"column 3"
],
"col1": [
{
"1": "row1col1"
},
{
"2": "row2col1"
],
"col2": [
{
"1": "row1col2"
},
{
"2": "row2col2"
],
"col3": [
{
"1": "row1col3"
},
{
"2": "row2col3"
]
}
]
Then using this dynamic array I created a table and stored it as finalArray
which was okay until I went to the body of my table to show data for col and row
<div *ngFor="let table of finalArray">
<span>{{table.name}}</span>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th *ngFor="let column of table.columns" scope="col">{{column}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of table.rows ; let i = index">
<td>{{row}}</td> // this works fine
<td *ngFor="let column of table.columns; let x = index"> {{table.['col' + x].[i+1]}}</td>
// this is the problem
</tr>
</tbody>
</table>
</div>
Note that the array was created dynamically so rows and columns is not fixed and col1 and col2 was created based on columns.
I attempt to something like table.col[index].[loop all values]?
You are almost there. Iterate thru columns in the second loop for more precision. Remove '.'s when getting elements. Interchange + 1 from i to x when getting columns and use Object.keys to get the array of key names so you can get the corresponding column content. I put it in a method for for readability
HTML
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th *ngFor="let column of table.columns" scope="col">{{column}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of table.rows ; let i = index">
<td>{{row}}</td>
<td *ngFor="let col of table.columns; let x = index">
{{getColumnContent(table['col'+(x+1)][i])}}
</td>
</tr>
</tbody>
</table>
Typescript
getColumnContent(col) {
return col[Object.keys(col)[0]] // always [0] as it contains a single element
}
Demo
I need to get the value in a row of a table on click and display it in popup
HTML:
<md-data-table-container>
<table md-data-table class="md-primary" md-progress="deferred">
<thead md-order="query.order" md-trigger="onorderchange">
<tr>
<th name="Task To Be Done"></th>
<th name="Office"></th>
<th name="Due Date"></th>
</tr>
</thead>
<tbody ng-click="showAlert($event)">
<tr ng-repeat="dessert in desserts.data" ng-click="showAlert($index)" flex-sm="100" flex-md="100" flex-gt-md="auto">
<td>{{dessert.task}}</td>
<td></td>
<td>{{dessert.due_on}}</td>
</tr>
</tbody>
</table>
</md-data-table-container>
JS:
$scope.desserts = {
"count": 6,
"data": [{
"task": "Frozen yogurt",
"type": "Ice cream"
}, {
"task": "Ice cream sandwich",
"type": "Ice cream"
}, {
"task": "Eclair",
"type": "Pastry"
}, {
"task": "Cupcake",
"type": "Pastry"
}, {
"task": "Jelly bean",
"type": "Candy"
}, {
"task": "Lollipop",
"type": "Candy"
}, {
"task": "Honeycomb",
"type": "Other"
}]
};
$scope.showAlert = function (index) {
$scope.obj = $scope.desserts.data[2];
$scope.task = $scope.obj.task;
alert($scope.task);
console.log($scope.task);
};
issue in my code is that i could get the value on the array which i have specified ".data[2]". Actually when i click a row in my table i need that value to be displayed to popup "sweetAlert". is there any solution
Don't pass the $index, as this can be a bit dangerous if the underlying data changes, and in this case it just forces you to re-get the item from the array.
Pass the actual item you want to display back to the alert.
<tr ng-repeat="dessert in desserts.data" ng-click="showAlert(dessert)" flex-sm="100" flex-md="100" flex-gt-md="auto">
<td>{{dessert.task}}</td>
<td></td>
<td>{{dessert.due_on}}</td>
</tr>
Don't assign to scope unless you really need it elsewhere.
$scope.showAlert = function (dessert) {
alert('Task:' + dessert.task);
// if you're just using a variable in this function, declare it locally
var dessertType = dessert.type;
console.log(dessertType);
};
See an example of $index causing issues:
http://codeutopia.net/blog/2014/11/10/angularjs-best-practices-avoid-using-ng-repeats-index/comment-page-1/