javascript - Svelte on:改变来得太晚
问题描述
我有一个 Svelte 应用程序:
- 允许您选择要查看的图表的下拉列表(饼图/条形图/日历)
- 带有要包含在图表中的变量的复选框面板。(不同的图表有不同的可用变量)
- 仅针对选定变量过滤我的数据的函数,然后将该数据传递到图表。
您可以在此处运行的完整代码:
<script>
let rawData = {
LevelTracker: [{ text: "headache" }, { text: "pain" }],
EventType: [{ text: "coffee" }, { text: "aspirin" }],
Event: [
{ time: 1500000000, text: "coffee" },
{ time: 1500030000, text: "aspirin" },
{ time: 1500230000, text: "coffee" },
// etc....
],
LevelChange: [
{ time: 1500000000, text: "headache", level: 2 },
{ time: 1500030000, text: "headache", level: 3 },
{ time: 1500230000, text: "pain", level: 2 },
// etc....
],
};
$: availableLTs = rawData.LevelTracker.map((e) => e.text);
$: availableETs = rawData.EventType.map((e) => e.text);
let schemas = [
{
name: "byTimeOfDay",
vars: [{ name: "X", et: true, lt: true }],
},
{
name: "lagBarChart",
vars: [
{ name: "X", min: 1, et: true, lt: false },
{ name: "Y", min: 1, max: 1, lt: true, et: true },
],
},
{
name: "calendar",
vars: [{ name: "X", et: true, lt: true }],
},
];
let chartsMap = {};
for (let schema of schemas) {
chartsMap[schema.name] = schema;
}
//let selectedChart = "lagBarChart";
//let selectedChart = "byTimeOfDay";
let selectedChart = "calendar";
function getInitSelectedVars(schemaVars) {
let selection = {};
for (let varSchema of schemaVars) {
selection[varSchema.name] = { ets: [], lts: [] };
}
return selection;
}
function initSelectedVars() {
console.log("in initSelectedVars");
selectedVars = getInitSelectedVars(schemaVars);
}
function makeChartData({ selectedVars, rawData }) {
console.log("in makeChartData");
for (let [key, value] of Object.entries(selectedVars)) {
// TODO: we filter rawData for just the selected vars, and return that data...
}
}
// this will be passed to the chart component
$: chartData = makeChartData({
selectedVars,
rawData,
});
$: schemaVars = chartsMap[selectedChart].vars;
$: selectedVars = selectedVars || getInitSelectedVars(schemaVars);
</script>
<main>
<h2>Select chart type</h2>
<select bind:value={selectedChart} on:change={initSelectedVars}>
{#each schemas as chart}
<option value={chart.name}>
{chart.name}
</option>
{/each}
</select>
<h2>Select your vars</h2>
{#each schemaVars as schemaVar}
<h3>
{schemaVar.name}
</h3>
{#if schemaVar.lt}
{#each availableLTs as ele}
<div class="form-check">
<label>
<input
type="checkbox"
class="form-check-input"
bind:group={selectedVars[schemaVar.name].lts}
value={ele}
/>
{ele}
</label>
</div>
{/each}
{/if}
{#if schemaVar.et}
{#each availableETs as ele}
<div class="form-check">
<label>
<input
type="checkbox"
class="form-check-input"
bind:group={selectedVars[schemaVar.name].ets}
value={ele}
/>
{ele}
</label>
</div>
{/each}
{/if}
{/each}
<!-- then we display the selected chart, like:
<calendar {chartData} />
-->
</main>
<style>
</style>
每次用户更改下拉菜单时,我们都需要重新初始化selectedVars
为与当前图表架构匹配的值。
例如,如果选择了日历,我们需要这样做:
selectedVars = {X: {ets: [], lts: []}}
但是如果选择了条形图,我们需要:
selectedVars = {X: {ets: [], lts: []}, Y: {ets: [], lts: []}}
我定义了一个执行此操作的函数,并将on:change={initSelectedVars}
其放入图表下拉列表中。但是,每次我将图表类型从“日历”更改为“条形图”时,我仍然会收到错误消息makeChartData
:
Uncaught (in promise) TypeError: Cannot read property 'lts' of undefined
at Object.mount [as m] (Debug.svelte:101)
at Object.mount [as m] (Debug.svelte:95)
at Object.mount [as m] (Debug.svelte:109)
at Object.update [as p] (Debug.svelte:90)
at update (index.mjs:764)
at flush (index.mjs:732)
我认为 on:change 函数只会在selectedVars
更改后运行,所以为时已晚。
有什么建议么?我的代码如下。
解决方案
您确定错误发生在makeChartData
函数中吗?
可能是这一行:bind:group={selectedVars[schemaVar.name].lts}
我还没有完全理解你的代码,但是应该可以selectedVars
使用响应式语句将值更改为所需的值。所以,我认为你不需要on:change
处理程序。
编辑:我想你想要这样的东西:https ://svelte.dev/repl/57d760278e0e4acfad536c1269bceba3?version=3.37.0
推荐阅读
- google-apps-script - 如何将表格单元格边框设置为虚线?
- twitter-bootstrap-3 - Bootstrap 轮播格式和样式
- c# - 监控多台机器 - 使用什么样的方法?
- java - 缺少 HFS 承诺错误:从 Apple Mail 应用程序拖放到 Java 应用程序在 Windows 中有效,但在 OSX 环境中无效
- c# - 排除参数导致错误 C# 的最佳方法
- acumatica - 使用 DeviceHub 打印 - 识别打印机访问组打印机
- maven - Maven Failsafe 不运行任何测试
- java - 图像未在简单 JFrame 中显示
- java - 用于部分持久性和序列化的 Java DTO 类设计?
- python - 如何模拟 python dict __str__ 方法?