[英]How to create a dynamic HTML table with Firebase?
I'm trying to create an HTML table that can be updated in real time with firebase as my users use my app. 我正在尝试创建一个HTML表,当用户使用我的应用程序时,可以使用firebase实时更新该表。 I'm really struggling on getting this to work, I don't really know where to start.
我真的很想让它开始工作,我真的不知道从哪里开始。
basically, all it needs to do is create a new table row and update its cells in real time as the user is interacting with my app. 基本上,它所要做的就是创建一个新的表行,并在用户与我的应用进行交互时实时更新其单元格。
Does anyone know of any good tutorials that could point me in the right direction? 有人知道有什么好的教程可以为我指明正确的方向吗? Examples of code on creating the HTML table would also be great!
创建HTML表的代码示例也很棒! thanks.
谢谢。
UPDATE: OK! 更新:好的! thanks to Isaiah Lee, I went out and looked up some tutorials for React.
感谢Isaiah Lee,我出去看看了React的一些教程。 I'm 90% there but there is one problem I can't seem to figure out...
我在那里90%,但似乎有一个我似乎无法解决的问题...
I'm able to update my table with new rows dynamically as the users use my app, but I can't get them to fill up with data. 当用户使用我的应用程序时,我可以动态地用新行更新表,但是我无法让它们填充数据。 I feel like I'm really close but my inexperience with React is holding me back here...
我觉得我真的很接近,但是我对React的经验不足使我退缩到这里...
for some reason, this loop here doesn't populate the td's with any data 由于某种原因,此循环不会在td中填充任何数据
render() {
return (
<div className="App">
<h1>Talkeetna Numbers</h1>
<table id="numbers">
<tbody>
<tr>
<th>Driver</th>
<th>Coach</th>
<th>Time</th>
<th>Total People</th>
<th>AM Train</th>
<th>PM Train</th>
<th>MEX</th>
<th>Employees</th>
<th>Seats Left</th>
</tr>
{this.state.rows.map(row =>
<tr>
<td>{this.state.driver}</td>
<td>{this.state.coach}</td>
<td>{this.state.time}</td>
<td>{this.state.totalPeople}</td>
<td>{this.state.amTrain}</td>
<td>{this.state.pmTrain}</td>
<td>{this.state.THEMEX}</td>
<td>{this.state.Employees}</td>
<td>{this.state.seatsLeft}</td>
</tr>)}
</tbody>
</table>
</div>
);
} }
Heres my components function 这是我的组件功能
componentDidMount()
{
const logsRef = firebase.database().ref('logs');
logsRef.on('child_added', snap => {
this.addRow(snap.getKey());
//rows.push(snap.getKey());
console.log("adding key: ", snap.getKey());
});
console.log("loading rows...");
for(var rowKey = 0; rowKey < this.state.rows.length; rowKey++)
{
const root = firebase.database().ref().child('logs/' + rowKey);
const driverRef = root.child('Driver');
const coachRef = root.child('Coach');
const timeRef = root.child('Time');
const totalPeopleRef = root.child('Total People');
const AMTrainRef = root.child('AM Train');
const PMTrainRef = root.child('PM Train');
const MEXRef = root.child('MEX');
const EmployeesRef = root.child('Employees');
const seatsLeftRef = root.child('Seats Left');
//sync with DB in real time
driverRef.on('value', snap => {
this.setState({
driver: snap.val()
})
});
coachRef.on('value', snap => {
this.setState({
coach: snap.val()
})
});
timeRef.on('value', snap => {
this.setState({
time: snap.val()
})
});
totalPeopleRef.on('value', snap => {
this.setState({
totalPeople: snap.val()
})
});
AMTrainRef.on('value', snap => {
this.setState({
amTrain: snap.val()
})
});
PMTrainRef.on('value', snap => {
this.setState({
pmTrain: snap.val()
})
});
MEXRef.on('value', snap => {
this.setState({
THEMEX: snap.val()
})
});
EmployeesRef.on('value', snap => {
this.setState({
Employees: snap.val()
})
});
seatsLeftRef.on('value', snap => {
this.setState({
seatsLeft: snap.val()
})
});
}
}
Sounds like you should look into some frontend framework. 听起来您应该研究一些前端框架。 In your particular use case, anything with 1-way binding will work (eg react).
在您的特定用例中,任何具有1向绑定的东西都可以工作(例如,反应)。 And of course, anything with 2-way binding will work as well (angular).
当然,任何带有2向绑定的东西也都可以工作(角度)。
Egghead.io has really well done, bite-size tutorials that can get you running shortly: https://egghead.io/browse/frameworks Egghead.io确实做得很好,一口大小的教程可以使您很快运行: https ://egghead.io/browse/frameworks
Edit: 编辑:
Okay, it's been over a year since I've last been working with react, but I have some ideas that could help. 好的,自从我上次进行反应以来已经一年多了,但是我有一些想法可以帮到您。
First, react is all about separating components and breaking things off into smaller bits. 首先,反应就是将组件分离并将其分解成较小的部分。 The idea is that you have some state change at the top level, those changes are propagated down into the nested components using props.
这个想法是您在顶层进行了一些状态更改,这些更改使用props向下传播到嵌套组件中。
I'd recommend you have a top level component that listens for changes in Firebase (I havent worked with FB in a long time either), and then sends those down to components that render based on the data. 我建议您有一个顶层组件,侦听Firebase中的更改(或者我很长时间没有使用FB),然后将这些更改发送到根据数据进行渲染的组件。 I recommend reading this article written by Dan Abramov (creator of Redux), which discusses smart vs dumb components: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
我建议阅读由Dan Abramov(Redux的创建者)撰写的这篇文章,其中讨论了智能组件和哑组件: https : //medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
Again, I haven't used react in a while, so I'll use pseudocode to describe how you might want to design this. 同样,我已经有一段时间没有使用react了,所以我将使用伪代码来描述您可能如何设计它。
Top Level Component This component should be the only place your app is interacting with Firebase. 顶级组件此组件应该是您的应用与Firebase进行交互的唯一位置。 You'll configure all the listeners here such that when new data is received, it simply propagates down to child components.
您将在此处配置所有侦听器,以便在接收到新数据时,它仅向下传播到子组件。
constructor() {
this.firebaseRef = firebase
.database()
.ref('logs');
this.state = {
logs: []
};
// when the table first loads, use the
// firebase ref to get all the current data
// and initialize/render the table. After this,
// you should only be listening for when a new row
// (or "log") is added. Pseudocode:
firebase.database().ref('logs')
.all()
.then(logs => {
// project all the logs into the model we need and set to
// component's row state
this.state.logs = logs.map(logMapper);
});
}
// takes in a log that you get from firebase and maps
// it to an object, modeled such that it contains all
// the information necessary for a single table row
logMapper(log) {
return {
driver: log.child('Driver'),
time: log.child('Time'),
...
};
}
componentDidMount() {
const logsRef = firebase
.database()
.ref('logs');
firebaseRef.on('child_added', log => {
this.state.logs.push(logMapper(log));
});
}
render() {
return (
<table id="numbers">
<thead>
<th>Driver</th>
<th>Coach</th>
<th>Time</th>
<th>Total People</th>
<th>AM Train</th>
<th>PM Train</th>
<th>MEX</th>
<th>Employees</th>
<th>Seats Left</th>
</thead>
<tbody>
{this.state.logs.map(row => <TableRow rowData="logs" />}
</tbody>
</table>
);
}
Row Component You have a separate component that receives a log object through props and renders a single row. 行组件您有一个单独的组件,该组件通过props接收日志对象并呈现单个行。
render() {
return (
<tr>
<td>{this.props.rowData.driver}</td>
<td>{this.props.rowData.coach}</td>
<td>{this.props.rowData.time}</td>
<td>{this.props.rowData.totalPeople}</td>
<td>{this.props.rowData.amTrain}</td>
<td>{this.props.rowData.pmTrain}</td>
<td>{this.props.rowData.THEMEX}</td>
<td>{this.props.rowData.Employees}</td>
<td>{this.props.rowData.seatsLeft}</td>
</tr>
);
}
The above TableRow is an example of a dumb component. 上面的TableRow是一个哑组件的示例。 It doesn't hold any internal state, nor really modify anything.
它没有任何内部状态,也没有任何修改。 It just takes what it's given via props and renders what it's supposed to.
它只是接受通过道具给出的内容,并渲染其应有的内容。
Again, you'll have to consider my examples above as pseudocode, it wouldn't work if you tried to copy and run it. 同样,您必须将我上面的示例视为伪代码,如果您尝试复制并运行它,它将无法正常工作。 But hopefully this gives you some insight into how to design components in react.
但是希望这可以使您对如何设计组件做出一些了解。 Remember, "everything is a component".
记住,“一切都是组成部分”。
Just a couple last notes: 最后几条注意事项:
Good luck! 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.