- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在研究解决方案
我已经创建了基本的树型表格,每当用户点击展开时,与点击行相关的数据将根据行数据显示在其下方
我已经实现了展开/折叠到 N 层嵌套的基本功能。
但我只遇到一个问题,所以基本上所有行都有基于具有多个值的数组的条件展开按钮
假设它是一个包含 3 个条目 county,city,state 的拆分数组
默认加载的数据将从 api 获取,现在我必须检查数组是否有可用的拆分!如果是,我会让展开按钮可见
考虑这个场景
const split = ["country","city","state"]
这是 Ui 的样子
+ Data_1
+ Data_2
单击按钮 + 新数据表行将根据下一个可用拆分呈现,在我们的例子中它是国家/地区,因此视觉表示就像
- Data_1
Country_1
Country_2
+ Data_2
这里的国家/地区没有展开按钮,因为用户还没有添加下一个拆分,让我们添加城市,并假设用户点击了 Country_1,这样数据会像
- Data_1
- Country_1
City_1
City_2
+ Country_2
+ Data_2
我的解决方案工作正常,直到这个级别现在假设用户已经从拆分中删除了国家和城市的所有节点应该删除并且 - data_1 的图标应该更改为 +
这是我的代码
import React, {useState, useEffect, useRef, Fragment} from "react";
import _ from "lodash";
import axios from "axios";
class TableRowData extends React.Component {
state = {
showIcon: false,
selection: [],
data: [],
splitOption: ["campid"]
};
constructor(props) {
super(props);
}
componentDidMount() {
const checkIfSplitExistOnMount = (currentSplit) => {
const i = _.findIndex(this.state.splitOption, function(el) {
return el === currentSplit;
});
if (this.state.splitOption[i + 1]) {
return this.state.splitOption[i + 1];
} else {
return null;
}
}
const getReportData = () => {
axios.get("https://jsonplaceholder.typicode.com/users?_start=0&_limit=1").then((res) => {
const rowData = res.data.map((row) => {
row.name = this.state.splitOption[0];
row.isExpanded = false;
row.currentSplit = this.state.splitOption[0];
row.nextSplit = checkIfSplitExistOnMount(this.state.splitOption[0])
row.parentId = 0;
row.isVisble = true;
//console.log(row)
return row;
});
this.setState({
data: rowData
}, () => { //console.log(this.state.data)
});
});
}
getReportData()
}
render() {
// update state function
const updateState = () => {
this.setState({
data: [...this.state.data],
splitOption: [...this.state.splitOption],
selection: [...this.state.selection],
}, () => {})
}
// recusively update parent and child
const recursion = (obj) => {
let row = obj;
row.isExpanded = row.isExpanded;
row.currentSplit = row.currentSplit;
row.nextSplit = checkIfSplitExist(row.currentSplit)
if (row.children && row.children.length > 0) { // check if has children
row.children.forEach(v => { // if has children do the same recursion for every children
recursion(v);
});
}
return row; // return final new object
}
const recursionDel = (obj,split) => {
var row = obj;
row.currentSplit = row.currentSplit;
row.nextSplit = checkIfSplitExist(row.currentSplit)
if (row.children && row.children.length > 0) { // check if has children
row.children.forEach(v => { // if has children do the same recursion for every children
recursionDel(v);
});
}
return row; // return final new object
}
// function to check if next split is there or not if there than return nextsplit
const checkIfSplitExist = (currentSplit) => {
const i = _.findIndex(this.state.splitOption, function(el) {
return el === currentSplit;
});
if(i !== -1) {
if (this.state.splitOption[i + 1]) {
return this.state.splitOption[i + 1];
} else {
return null;
}
}
}
// recursive update whenever split added
const recursiveUpdate = (data) => {
const prevData = [...data];
return prevData.map((row) => {
const updatedData = recursion(row);
return row;
});
}
// function to delete child and parent node recursively
const recursiveDelete = (data,split) => {
const prevData = [...data];
return prevData.map((row) => {
const data = recursionDel(row,split);
return row;
});
}
const addNewSplit = (split) => {
const i = _.findIndex(this.state.splitOption, function(el) {
return el === split;
});
if(i === -1) {
this.setState(
{
splitOption:[...this.state.splitOption,split]
},
()=>{
var rowData = recursiveUpdate(this.state.data)
this.setState({data:rowData})
}
);
} else {
const prevData = [...this.state.splitOption];
var index = prevData.indexOf(split);
prevData.splice(index,1)
if(index!==-1) {
this.setState(
{
splitOption:prevData
},
()=> {
var rowData = recursiveDelete(this.state.data,split)
this.setState({data:rowData})
}
)
}
}
}
// add lazyload expand data
const ExpandableTableRow = ({rows}) => {
const expandRow = (row) => {
row.children = [
{
id: "_" + Math.random().toString(36).substr(2, 5),
name: row.id + "_" + row.nextSplit,
isExpanded: false,
parentId: row.id,
currentSplit: row.nextSplit,
nextSplit: checkIfSplitExist(row.nextSplit),
isVisble:true
}, {
id: "_" + Math.random().toString(36).substr(2, 5),
name: row.id + "_" + row.nextSplit,
isExpanded: false,
parentId: row.id,
currentSplit: row.nextSplit,
nextSplit: checkIfSplitExist(row.nextSplit),
isVisble:true
}
];
row.isExpanded = true;
updateState();
};
// call whenever - click
const collapseRow = (row) => {
delete row.children;
row.isExpanded = false;
updateState();
};
// toggle
const ExpandCollapsToggle = ({row, expandRow, collapseRow}) => {
// display +/- only if nextsplit is not undefined or null
if (row.nextSplit) {
if (row.isExpanded === true) {
return (<button type="button" onClick={() => collapseRow(row)}>
-
</button>);
} else {
return (<button type="button" onClick={() => expandRow(row)}>
+
</button>);
}
} else {
return null;
}
};
if (rows) {
return rows.map((row) => {
// if(!_.isEmpty(row)) {
return (<Fragment key={row.id}>
<tr key={row.id}>
<td>
<ExpandCollapsToggle row={row} expandRow={expandRow} collapseRow={collapseRow}/>{" "}
{row.split}
- {row.id}
</td>
<td>{row.name}</td>
</tr>
<ExpandableTableRow rows={row.children}/>
</Fragment>);
// }
});
} else {
return null;
}
};
const splitData = this.state.splitOption.map((ob) => {
return (<Fragment key={ob}><span>{ob}</span> > </Fragment>)
})
if (this.state.data) {
return (
<Fragment>
{splitData} <br/>
<button onClick = {()=>addNewSplit("name")}>camp name</button>
<button onClick = {()=>addNewSplit("os")}>os</button>
<button onClick = {()=>addNewSplit("country")}>country</button>
<ExpandableTableRow rows={this.state.data} />
</Fragment>
);
} else {
return null;
}
}
}
export default TableRowData;
我还创建了 codesandbox.io 示例 - Link
这是你如何使用 ui 来复制场景
最佳答案
import React, { useState, useEffect, useRef, Fragment } from "react";
import axios from "axios";
const test_data = [{
"id":1,
"name":"Leanne Graham",
"username":"Bret",
"email":"Sincere@april.biz",
"address":{
"street":"Kulas Light",
"suite":"Apt. 556",
"city":"Gwenborough",
"zipcode":"92998-3874",
"geo":{
"lat":"-37.3159",
"lng":"81.1496"
}
},
"phone":"1-770-736-8031 x56442",
"website":"hildegard.org",
"company":{
"name":"Romaguera-Crona",
"catchPhrase":"Multi-layered client-server neural-net",
"bs":"harness real-time e-markets"
}
}];
class TableRowData extends React.Component {
constructor(props) {
super(props);
this.state = {
showIcon: false,
selection: [],
data: [],
splitOption: ["campid"]
};
}
// function to check if next split is there or not if there than return nextsplit
checkIfSplitExist = (currentSplit) => {
const i = this.state.splitOption.indexOf(currentSplit);
if (i > -1 && this.state.splitOption[i + 1]) {
return this.state.splitOption[i + 1];
}
return null;
}
getReportData = () => {
// axios.get("https://jsonplaceholder.typicode.com/users?_start=0&_limit=1").then(({data}) => {
this.setState({
data: test_data.map((row) => {
row.name = this.state.splitOption[0];
row.isExpanded = false;
row.currentSplit = this.state.splitOption[0];
row.nextSplit = this.checkIfSplitExist(this.state.splitOption[0])
row.parentId = 0;
row.isVisble = true;
console.log(row)
return row;
})
});
// });
}
componentDidMount() {
this.getReportData()
}
render() {
// update state function
const updateState = () => {
this.setState({
data: [...this.state.data],
splitOption: [...this.state.splitOption],
selection: [...this.state.selection],
}, () => { })
}
const recursionUpdateAndDeleteRow = (parentRow, childRow, split, index = 0) => {
childRow.children && childRow.children.forEach((r) => {
recursionUpdateAndDeleteRow(childRow, r, split, index + 1);
});
if (parentRow && split.indexOf(childRow.currentSplit) == -1) {
delete parentRow.children;
}
childRow.currentSplit = split[index];
childRow.nextSplit = split[index + 1] || null;
if (!childRow.children) {
childRow.isExpanded = false;
}
}
const recursionUpdateAndDeleteRows = (rows, split) => {
const _copy = [...rows];
_copy.forEach((row) => {
recursionUpdateAndDeleteRow(null, row, split);
});
return _copy;
}
const toggleSplit = (split) => {
const index = this.state.splitOption.indexOf(split);
let currentSplitOptions = [...this.state.splitOption];
if (index > -1) {
currentSplitOptions.splice(index, 1)
}
else {
currentSplitOptions.push(split);
}
const _data = recursionUpdateAndDeleteRows(this.state.data, currentSplitOptions);
this.setState({
splitOption: currentSplitOptions,
data: _data
})
}
// add lazyload expand data
const ExpandableTableRow = ({ rows }) => {
const expandRow = (row) => {
row.children = [
{
id: "_" + Math.random().toString(36).substr(2, 5),
name: row.id + "_" + row.nextSplit,
isExpanded: false,
parentId: row.id,
currentSplit: row.nextSplit,
nextSplit: this.checkIfSplitExist(row.nextSplit),
isVisble: true
}, {
id: "_" + Math.random().toString(36).substr(2, 5),
name: row.id + "_" + row.nextSplit,
isExpanded: false,
parentId: row.id,
currentSplit: row.nextSplit,
nextSplit: this.checkIfSplitExist(row.nextSplit),
isVisble: true
}
];
row.isExpanded = true;
updateState();
};
// call whenever - click
const collapseRow = (row) => {
delete row.children;
row.isExpanded = false;
updateState();
};
// toggle
const ExpandCollapsToggle = ({ row }) => {
// display +/- only if nextsplit is not undefined or null
if (row.nextSplit) {
if (row.isExpanded) {
return (
<button type="button" onClick={() => collapseRow(row)}>
-
</button>
);
}
return (
<button type="button" onClick={() => expandRow(row)}>
+
</button>
);
}
return null;
};
if (rows) {
return rows.map((row) => {
return (
<Fragment key={row.id}>
<tr key={row.id}>
<td>
<ExpandCollapsToggle
row={row}
/>
{" "}{row.split} - {row.id}
</td>
<td>{row.name}</td>
</tr>
<ExpandableTableRow rows={row.children} />
</Fragment>
);
});
} else {
return null;
}
};
if (this.state.data) {
return (
<Fragment>
{this.state.splitOption.join(', ')} <br />
<button onClick={() => toggleSplit("name")}>
camp name
</button>
<button onClick={() => toggleSplit("os")}>os</button>
<button onClick={() => toggleSplit("country")}>country</button>
<br />
<ExpandableTableRow rows={this.state.data} />
</Fragment>
);
} else {
return null;
}
}
}
export default function App() {
return (
<div>
<TableRowData />
</div>
);
}
在这里工作 example
关于javascript - 如何从对象中递归地删除子对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66397465/
我知道如何通过iPhone开发创建sqlite数据库、向其中插入数据、删除行等,但我试图以编程方式删除整个数据库本身,但没有得到任何帮助。请有人指导我如何通过代码从设备中删除/删除整个 sqlite
请帮助指导如何在 Teradata 中删除数据库。 当我运行命令DROP DATABASE database_name时,我收到错误消息: *** Failure 3552 Cannot DROP d
Azure 警报规则的删除命令似乎不起作用,尝试了下面的方法,它返回状态为无内容,并且警报未被删除 使用的命令Remove-AzAlertRule -ResourceGroup "RGName"-Na
我在 flex 搜索中为大约50000个视频建立了索引,但是当它达到52000左右时,所有数据都被删除。嗯,这对我来说真的很奇怪,我没有为ES设置任何Heap大小或最小或最大大小的内存大小,因此它们没
我正在处理的问题是表单错误“输入由字母、数字、下划线或连字符组成的有效‘slug’。” 以下是我的表单字段验证: def clean_slug(self): slug = self.c
阅读文档,我希望 $("#wrap2").remove(".error") 从 中删除所有 .error 元素#wrap2。然而看看这个 JSFiddle: http://jsfiddle.net/h
嗨,我第一次尝试发现 laravel 我从 laravel 4.2 开始,我刚刚创建了一个新项目,但我误以为我写了这样的命令行 composer create-project laravel/lara
我已经在网上搜索了很长一段时间,但我找不到如何完全删除 apache 2.4 。 使用: Windows 7 c:\apache24\ 我已经尝试了所有命令,但没有任何效果。 httpd -k shu
可能是一个简单的答案,所以提前道歉(最少的编码经验)。 我正在尝试从任何列中删除具有特定字符串(经济 7)的任何行,并且一直在尝试离开此线程: How to drop rows from pandas
有几种方法可以删除/移除 vector 中的项目。 我有一个指针 vector ,我需要在类的析构函数中删除所有指针。 什么是最有效/最快甚至最安全的方式? // 1º std::for_each(v
我安装了一个 VNC 服务器并在某处阅读了我必须安装 xinetd 的信息。稍后我决定删除 VNC 服务器,所以我也删除了 xinetd。似乎 xinetd 删除了一些与 plesk 相关的文件,如果
我制作了一个从我们的服务器下载视频的应用。问题是: 当我取消下载时,我打电话: myAsyncTask.cancel(true) 我注意到,myAsyncTask 并没有在调用取消时停止...我的 P
是否可以在使用DELETE_MODEL删除模型之前检查模型是否存在我试图避免在尝试删除尚未创建的模型时收到错误消息。基本上我正在寻找对应的: DROP TABLE IF EXISTS 但对于模型。 最
我已经有了这个代码: 但它仍然会生成一个表行条目。 我想做的是,当输入的数量为0时,表行将被删除。请耐心等待,因为我是 php 和 mySQL 编码新手。 最佳答案 您忘记执行查询。应该是 $que
在 SharePoint 中,如果您删除/修改重复日历条目的单次出现,则不会真正删除/修改任何内容 - 相反,会创建一个新条目,告诉 SP 对于特定日期,该事件不存在或具有新参数. 因此,这可以通过删
在 routes.php 中我有以下路由: Route::post('dropzone', ['as' => 'dropzone.upload', 'uses' => 'AdminPhotoContr
在我的应用程序中,我正在尝试删除产品。当我第一次删除产品时,它会成功并且 URL 更改为/remove_category/15。我正在渲染到同一页面。现在,当我尝试删除另一个产品时,网址更改为/rem
这个问题被问了很多次,但给出的答案都是 GNU sed 特定的。 sed -i '' "/${FIND}/,+2d""$FILE" 给出“预期的上下文地址”错误。 有人可以给我一个例子,说明如何使用
在使用 V3 API 时,我找不到任何方法来删除和清理 Google map 。 我已经在 AJAX 站点中运行它,所以我想完全关闭它而无需重新加载页面。 我希望有一个 .unload() 或 .de
是否可以创建一个 Azure SQL 数据库用户来执行以下操作: 针对所有表和 View 进行 SELECT 创建/更改/删除 View 但用户不应该不拥有以下权限: 针对任何表或 View 插入/更
我是一名优秀的程序员,十分优秀!