我有以下JSON数据:
{
"languageKeys": [{
"id": 1,
"project": null,
"key": "GENERIC.WELCOME",
"languageStrings": [{
"id": 1,
"content": "Welcome",
"language": {
"id": 1,
"key": "EN"
}
}]
}, {
"id": 2,
"project": null,
"key": "GENERIC.HELLO",
"languageStrings": [{
"id": 2,
"content": "Hej",
"language": {
"id": 2,
"key": "DK"
}
}, {
"id": 5,
"content": "Hello",
"language": {
"id": 1,
"key": "EN"
}
}]
}, {
"id": 3,
"project": null,
"key": "GENERIC.GOODBYE",
"languageStrings": []
}]
}我希望转换成一个表,其中的列是可变的。
表输出应如下所示:
------------------------------------------------
| Key | EN | DK | SE | [...] |
| GENERIC.WELCOME | Welcome | | | |
| GENERIC.HELLO | Hello | Hej | | |
| GENERIC.GOODBYE | | | | |
------------------------------------------------正如您所看到的,该表在行和列中都是动态的,我正在努力弄清楚如何在"EN“、"DK”、"SE“中映射正确的数据……字段添加到正确的列,因为当我从API的JSON响应中获取它们时,它们不一定是按顺序排列的。
到目前为止,我得到了以下呈现函数:
private static renderLanguageKeysTable(languageKeys: ILanguageKey[], languages: ILanguage[]) {
return <table>
<thead>
<tr>
<td>Key</td>
{languages.map(language =>
<td key={language.id}>{language.key}</td>
)}
</tr>
</thead>
<tbody>
{languageKeys.map(languageKey =>
<tr key={languageKey.id}>
<td>{languageKey.key}</td>
{languages.map(language =>
<td key={language.id}>
</td>
)}
</tr>
)}
</tbody>
</table>
;
}这是正常工作的,唯一缺少的部分是列中的数据。
我尝试过filter和map的各种变体,但没有一个能达到我想要的效果。
我正在使用ReactJS并用typescript (es2015)书写
澄清一点:列将始终由API定义,行不能具有指向不存在的列的ID,因为它们在后端是相关的。但是,可能会发生某些行没有所有列的情况,在这种情况下,它们应该是空白的
发布于 2018-01-21 19:22:05
我最终使用了一种与建议不同的方法(在一夜良好的睡眠和一些思考之后)
基本上,我为每个单独的单元格创建了一个新组件,在代码的表格端产生了以下呈现:
private static renderLanguageKeysTable(languageKeys: ILanguageKey[], languages: ILanguage[]) {
return <table>
<thead>
<tr>
<th>Key</th>
{languages.map(language =>
<th key={language.id}>{language.key}</th>
)}
</tr>
</thead>
<tbody>
{languageKeys.map(languageKey =>
<tr key={languageKey.id}>
<td>{languageKey.key}</td>
{languages.map(language =>
<Cell language={language} languageKey={languageKey} key={language.id} />
)}
</tr>
)}
</tbody>
</table>
;
}下面是渲染每个单元格的代码:
import * as React from "react";
export class Cell extends React.Component {
render() {
let string: any;
if (this.props.languageKey && this.props.languageKey.languageStrings) {
let languageString =
this.props.languageKey.languageStrings.find((i: any) => i.language.id === this.props.language.id);
if (languageString === null || languageString === undefined) {
string = "";
} else {
string = languageString.content;
}
} else {
string = "";
}
return <td>
{string}
</td>;
}
props: any;
}发布于 2018-01-21 02:22:44
const findDistinctLang = (langKeys) => {
let langString = []
langKeys.forEach((element) => {
if(element.languageStrings.length !== 0) {
langString = [...langString, ...element.languageStrings]
}
})
const langArr = []
langString.forEach((element) => {
if (langArr.indexOf(element.language.key) === -1) {
langArr.push(element.language.key)
}
})
return langArr
}
class Table extends React.Component {
state = {
"languageKeys": [{
"id": 1,
"project": null,
"key": "GENERIC.WELCOME",
"languageStrings": [{
"id": 1,
"content": "Welcome",
"language": {
"id": 1,
"key": "EN"
}
}]
}, {
"id": 2,
"project": null,
"key": "GENERIC.HELLO",
"languageStrings": [{
"id": 2,
"content": "Hej",
"language": {
"id": 2,
"key": "DK"
}
}, {
"id": 5,
"content": "Hello",
"language": {
"id": 1,
"key": "EN"
}
}]
}, {
"id": 3,
"project": null,
"key": "GENERIC.GOODBYE",
"languageStrings": [{
"id": 2,
"content": "Hej",
"language": {
"id": 2,
"key": "DK"
}
},{
"id": 5,
"content": "XYZ",
"language": {
"id": 7,
"key": "XYZ"
}
}]
}]
}
getContentName = (languageSet, langName) => {
return _.find(languageSet.languageStrings, function(o) { return o.language.key === langName })
}
render() {
const lanKeyArr = findDistinctLang(this.state.languageKeys)
return ( <
table >
<
thead >
<
tr >
<
td > Key < /td> {
lanKeyArr.map((lang) => {
return ( < td > {
lang
} < /td>)
})
} <
/tr> <
/thead> <
tbody >
{
this.state.languageKeys.map((languageSet) => {
return(
<tr>
<td>{languageSet.key}</td>
{[...lanKeyArr].map((element, index) => {
const contentObj = this.getContentName(languageSet, element)
return (
<td>{contentObj && contentObj.content || ""}</td>
)
})
}
</tr>
)
})
}
<
/tbody> < /
table >
)
}
}
ReactDOM.render(<Table />,document.getElementById("root"))<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
我已经基于你提供的测试数据实现了,注意:你可以让它更干净,通过这个例子给你一个想法
发布于 2018-01-21 03:44:51
您可以解析对象并根据预期的渲染来渲染表。
请注意,没有使用ReactJS的经验,也没有尝试过TypeScript
let languages = {"languageKeys":[{"id":1,"project":null,"key":"GENERIC.WELCOME","languageStrings":[{"id":1,"content":"Welcome","language":{"id":1,"key":"EN"}}]},{"id":2,"project":null,"key":"GENERIC.HELLO","languageStrings":[{"id":2,"content":"Hej","language":{"id":2,"key":"DK"}},{"id":5,"content":"Hello","language":{"id":1,"key":"EN"}}]},{"id":3,"project":null,"key":"GENERIC.GOODBYE","languageStrings":[]}]};
const table = document.querySelector("table");
const thead = table.querySelector("thead").querySelector("tr");
const tbody = table.querySelector("tbody");
Object.values(languages.languageKeys).forEach(({key, languageStrings}) => {
// check if `languageStrings` array has `.length` greater than `0`
if (languageStrings.length) {
languageStrings.forEach(({content, language:{key:lang}}) => {
console.log(key, content, lang);
// use block scopes
{
// check if the `lang` is already appended to `<thead>`
if (![...thead.querySelectorAll("td")].find(({textContent}) => textContent === lang)) {
let td = document.createElement("td");
td.textContent = lang;
thead.appendChild(td);
}
}
{
// append `key`
let tr = document.createElement("tr");
let tdKey = document.createElement("td");
tdKey.textContent = key;
tr.appendChild(tdKey);
// append `content`
let tdContent = document.createElement("td");
tdContent.textContent = content;
tr.appendChild(tdKey);
tr.appendChild(tdContent);
tbody.appendChild(tr);
// append a `<td>` for placing `<td>` in correct column
// not an optimal approach, adjust if necessary
if ([...thead.querySelectorAll("td")].findIndex(el => el.textContent === lang) === tr.children.length) {
tr.insertBefore(document.createElement("td"), tr.lastElementChild);
};
}
})
} else {
// handle empty `languageStrings` array
let tr = document.createElement("tr");
let tdKey = document.createElement("td");
tdKey.textContent = key;
tr.appendChild(tdKey);
tbody.appendChild(tr);
}
})<table>
<thead>
<tr>
<td>Key</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
https://stackoverflow.com/questions/48358984
复制相似问题