问题
In my angular 6 application, i am making a table with the contents from products
array like,
Ts:
products: any = {
"productOne": [
{
"id": 1, "product_name": "Product One",
"productOneProperties": [
{ "id": 1, "property_name": "Length", "property_value": "12cm" },
{ "id": 2, "property_name": "Width", "property_value": "10cm" },
{ "id": 3, "property_name": "Height", "property_value": "20cm" },
]
}
],
"productTwo": [
{
"id": 2, "product_name": "Product Two",
"productTwoProperties": [
{ "id": 1, "property_name": "Length", "property_value": "15cm" },
{ "id": 2, "property_name": "Width", "property_value": "12cm" },
{ "id": 2, "property_name": "Size", "property_value": "Medium" }
]
}
]
}
Html:
<table>
<thead>
<tr>
<th>
Property Details
</th>
<th>
{{productOneDetails}}
</th>
<th>
{{productTwoDetails}}
</th>
</tr> <br>
</thead>
<tbody>
<tr *ngFor="let item of mergedArray">
<td> {{ item.property_name }} </td>
<td> {{ item.type === "one" ? item.property_value: '-' }} </td>
<td> {{ item.type === "two" ? item.property_value: '-' }} </td>
</tr>
</tbody>
</table>
Here i have two separate products and properties in which the property name such as Length
and Width
has repeated for both products with different values..
Working stackblitz: https://stackblitz.com/edit/angular-9yzwss
Current result:
Property Details Product One Product Two
Length 12cm -
Width 10cm -
Height 20cm -
Length - 15cm
Width - 12cm
Size - Medium
Expected Result:
Property Details Product One Product Two
Length 12cm 15cm
Width 10cm 12cm
Height 20cm -
Size - Medium
Kindly help me to achieve the expected result by displaying the duplicate property name as unique and display the values adjacent.. If the property and value is not there then it needs to have "-"..
KIndly helpme to convert the current result into expected result..
回答1:
First of all your structure is quite wrongly added, you must consider your structure using flattern, It would be quite easier if you do so.
Let's think about handling this structure.
You need three variables defined in your component
headers: any;
data: any;
properties:any;
First you need to get the headers
var headers = Object.keys(this.products).reduce((prev, next) => {
prev.push({ name: this.products[next][0].product_name, id: next });
return prev;
}, []);
Then, get properties and data
let data = [];
let propertiesData = [];
headers.forEach(a => {
const properties = this.products[a.id][0][a.id + "Properties"];
data.push({id:a,properties:properties});
propertiesData.push(properties);
});
Then assign this variables to the header,data and properties
propertiesData = propertiesData.flat().filter((thing, index, self) =>
index === self.findIndex((t) => (
t.property_name === thing.property_name
))
)
this.headers = headers;
this.data = data;
this.properties = propertiesData;
So, you have three things now, headers data and properties which are unique,
Now, you need one method which will filter out this property names against the data,
getPropertyData(propertyName,item){
var value= item.properties.filter(a=> a.property_name === propertyName);
if(value.length>0){
return value[0].property_value;
}else{
return "-";
}
}
Now, in your view you can restructure your table to like this
<table>
<thead>
<tr>
<th>
Property Details
</th>
<th *ngFor="let item of headers">
{{item.name}}
</th>
</tr> <br>
</thead>
<tbody>
<tr *ngFor="let item of properties">
<td>{{item.property_name}}</td>
<td *ngFor="let itemData of data">
{{getPropertyData(item.property_name,itemData)}}
</td>
</tr>
</tbody>
</table>
So, this will filter out the properties data against the products.
Here is the stackblitz demo. remember there are some drawbacks using the structure. like your third property must be a name of productThreeProperties
回答2:
Something like this
There's probably a better way of formatting the data, but the idea should be pretty much the same. Alternatively you could just try to format the objects in the following format:
[
{ "propName": "length", "one": 12, "two": 20 },
{ "propName": "width", "one": 12, "two": '-'}
...
]
Or combining the "one" and "two" into an array to make expansion easier.
回答3:
the result is not correct because your merging the product logic is wrong. i having done some minor changes to show how you can correct the data to show what you want.
ngOnInit() {
this.mergedProductProperties = {};
this.products.productOne.forEach(element => {
this.productOneDetails = element.product_name;
element.productOneProperties.type = "one";
element.productOneProperties.forEach(item => {
this.mergedProductProperties[item.property_name] =this.mergedProductProperties[item.property_name] || [];
this.mergedProductProperties[item.property_name][0] = item.property_value;
});
});
this.products.productTwo.forEach(element => {
this.productTwoDetails = element.product_name;
element.productTwoProperties.type = "two";
element.productTwoProperties.forEach(item => {
this.mergedProductProperties[item.property_name] = this.mergedProductProperties[item.property_name] || [];
this.mergedProductProperties[item.property_name][1] = item.property_value;
});
});
console.log(this.mergedProductProperties);
for(var key in this.mergedProductProperties){
this.mergedArray.push({
property_name: key,
property_value: this.mergedProductProperties[key]
})
}
console.log(this.mergedArray);
}
html will be change by
<tbody>
<tr *ngFor="let item of mergedArray">
<td> {{ item.property_name }} </td>
<td *ngFor="let val of item.property_value">{{val}}</td>
</tr>
</tbody>
来源:https://stackoverflow.com/questions/53827050/remove-duplicate-names-in-a-column