Loading [MathJax]/jax/output/CommonHTML/config.js
社区首页 >问答首页 >如何更新js函数中的x-data组件

如何更新js函数中的x-data组件
EN

Stack Overflow用户
提问于 2022-01-17 03:17:07
回答 1查看 1.5K关注 0票数 0

Q1:

我正在尝试创建一个表单,它使用从API获取的初始值填充。每次用户编辑表单中的任何字段时,都应该向API发送POST请求,然后更新初始值。我的当前解决方案可以工作,但是当我在django模板中的for-循环中使用它时,生成的html文件的可读性并不理想,因为脚本重复了很多次。我认为将获取脚本提取到函数将使模板更易读,但我不知道如何更新包含用户在函数表单中给出的所有值的x-data组件的内容。

当前的解决方案如下(样式等不必要地清理):

代码语言:javascript
代码运行次数:0
复制
    <form action="/submitcars" method="POST" 
        x-data="{ dynamic_cars: [] }"
        x-init="dynamic_cars = await (await fetch('/dynamic_cars')).json()">
        {% csrf_token %}
        <div class="row-container">
            {% for row in rows %}
                {% for i in 0|range:3 %}
                  <div class="input_container car-{{i}}" x-show="open">
                    <div class="edited_icon" x-show="dynamic_cars.cars[{{i}}].{{row.row_id}}.user_edited === 'true'">
                      <i class="material-icons refresh" @click="dynamic_cars.cars[{{i}}].{{row.row_id}}.user_edited = 'false'">refresh</i>
                    </div>
                    <div class="edited_icon" x-show="dynamic_cars.cars[{{i}}].{{row.row_id}}.user_edited === 'false'"></div>
                    <input required
                    step="any"
                    id=id_form_car_{{i}}-{{row.row_id}}
                    name=form_car_{{i}}-{{row.row_id}}
                    type="{{row.html_type}}"
                    tabindex="{{i}}" 
                    x-model.lazy="dynamic_cars.cars[{{i}}].{{row.row_id}}.value"
                    @change= "dynamic_cars.cars[{{i}}].{{row.row_id}}.user_edited = 'true',
                    dynamic_cars = await (
                    await fetch('/dynamic_cars', {
                      method: 'POST', 
                      headers: {
                        'Content-Type': 'application/json',
                        'X-CSRFToken': document.head.querySelector('meta[name=csrf-token]').content  
                    },
                    body: JSON.stringify(dynamic_cars)
                    })).json()"></input>
                    <div class="unit" x-text="dynamic_cars.cars[{{i}}].{{row.row_id}}.unit"></div>
                  </div>
                {% endfor %}
            {% endfor %}
        </div>
        <div class="submit-button">
          <button type="submit" value="submit">Save</button>
        </div>
    </form>
        ...

编辑:添加了django循环和变量。row.row_id有一个属性名,它告诉我在CSS网格的每一行上显示的信息(make、model等)。所以这三辆车都有这些特性。Row.row_id与dynamic_cars API响应中的属性名匹配:

代码语言:javascript
代码运行次数:0
复制
cars: [
        {
          {make: {value: "Toyota", unit: "", user_edited: "false"},
          {model: {value: "Camry", unit: "", user_edited: "false"},
          ...
          70+ more properties for each car
          ...
        },
        {...},
        {...}
      ]

与其在x-on:change之后进行整个后置提取,不如使用以下内容:

代码语言:javascript
代码运行次数:0
复制
x-on:change="postCars(dynamic_cars)"

<script>
    async function postCars(dynamic_cars) {
      response = await fetch('/dynamic_cars', {
        method: 'POST', 
        headers: {
          'Content-Type': 'application/json',
          'X-CSRFToken': document.head.querySelector('meta[name=csrf-token]').content  
      },
      body: JSON.stringify(dynamic_cars)
      })
      .then(response => {
          if(response.ok) return response.json();
             })
    }
</script>

通过这样做,我可以看到脚本中的POST请求在其有效负载中具有dynamic_cars中的数据,并且响应是正确的,但是如果编辑输入,则dynamic_cars对象被设置为空,并且表单中的初始值消失。应该如何正确地做到这一点?

Q2:

我的另一个问题有点离题,但可能与javascript的基本知识有关,即浏览器开发工具中的控制台显示错误消息:

代码语言:javascript
代码运行次数:0
复制
Alpine Expression Error: Cannot read properties of undefined (reading 'value')

Expression: "dynamic_cars.cars[1].make.value"

AND

Uncaught TypeError: Cannot read properties of undefined (reading '1')

这是否意味着我必须按照API返回的那样在x数据中定义/初始化dynamic_cars?如果API响应非常复杂,并且有大量的数据,甚至是未知的呢?编写x-data="{}“open将意味着数百行javascript,由于当前解决方案的工作方式不同,除了控制台错误之外,我不需要编写和维护这些代码。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-18 04:33:34

在控制台中看到这些错误消息的原因是试图将表单字段绑定到不存在的对象。在Alpine.js环境中,只有一个空列表:x-data="{ dynamic_cars: [] }"。当Alpine.js最初尝试将输入字段绑定到相应的变量(例如dynamic_cars.cars[1].make.value )时,dynamic_cars甚至没有cars属性,实际上,它甚至不是一个对象,而是一个列表,因此也存在类型错误。

在错误的数据绑定周期之后,Alpine.js执行您在x-init中提供的获取后端并最终更新dynamic_cars变量的代码,因此现在它有了以前尝试绑定表单字段的属性/字段。令人惊讶的是,它仍然在某种程度上起作用,但IMHO它是相当不明确的行为,应该避免。

但是,由于您知道表单中的项/属性的数量,因此为它们创建正确的JS数据结构非常简单,因此Alpine.js可以将它们绑定到相应的表单字段。在获取后端之后,我们只需用获取的数据更新这个对象,Alpine.js就可以自动更新DOM。

代码语言:javascript
代码运行次数:0
复制
<form action="/submitcars" method="POST" x-data="carsForm" @change="postCars">
  <div>
  {% for row in rows %}
      {% for i in 0|range:3 %}
        <div class="input_container car-{{i}}" x-show="open">
          <div class="edited_icon" x-show="dynamic_cars.cars[{{i}}].{{row.row_id}}.user_edited">
            <i class="material-icons refresh" @click="dynamic_cars.cars[{{i}}].{{row.row_id}}.user_edited = false">refresh</i>
          </div>
          <div class="edited_icon" x-show="dynamic_cars.cars[{{i}}].{{row.row_id}}.user_edited"></div>
          <input required
                step="any"
                id=id_form_car_{{i}}-{{row.row_id}}
                name=form_car_{{i}}-{{row.row_id}}
                type="{{row.html_type}}"
                tabindex="{{i}}"
                x-model.lazy="dynamic_cars.cars[{{i}}].{{row.row_id}}.value" />
          <div class="unit" x-text="dynamic_cars.cars[{{i}}].{{row.row_id}}.unit"></div>
        </div>
      {% endfor %}
  {% endfor %}
  </div>
  <div class="submit-button">
    <button type="submit" value="submit">Tallenna</button>
  </div>
</form>


<script>
document.addEventListener('alpine:init', () => {
  Alpine.data('carsForm', () => ({
    dynamic_cars: {cars: {
    {% for i in 0|range:3 %}
    {{ i }}: {
      {% for row in rows %}
      {{ row.row_id }}: {value: '', user_edited: true, unit: ''},
      {% endfor %}
    },
    {% endfor %}
    }},

    init() {
      this.getCars()
    },

    getCars() {
      // ... fetch backend as usual

      // Sync new data with local this.dynamic_cars
      this.syncData(response.json())
    },

    syncData(new_data) {
      for (let i in new_data.cars) {
        let car = new_data.cars[i]
        for (let property_name in car) {
          for (let prop_attr of ['value', 'unit', 'user_edited']) {
            this.dynamic_cars.cars[i][property_name][prop_attr] = car[property_name][prop_attr]
          }
        }
      }
    },

    postCars() {
      // Post to the backend with payload: JSON.stringify(this.dynamic_cars)

      // Sync response data with local this.dynamic_cars
      this.syncData(response.json())
    }
  }))
})
</script>

我们的Alpine.js组件名为carsForm,我们在alpine:init事件中使用了Alpine.data(),以确保在我们的环境中Alpine.js已经就绪。您可以看到,HTML只包含极小的与Alpan.js相关的属性:x-data@change以及数据绑定属性。

首先,我们创建空的dynamic_cars Alpine.js变量,该变量具有尽可能多的行/项/属性/等等,因此Alpine.js可以将它们绑定到各自的表单字段。

在从getCars()执行的init()方法中,我们获取后端并使用响应数据作为参数调用syncData()函数。此函数迭代深度嵌套的数据结构,并更新本地dynamic_cars变量中的相应值。之后,Alpine.js更新DOM。

在用户更新表单字段后,@change指令调用我们的postCars()方法,该方法使用有效负载dynamic_cars将文章发送到后端。当后端响应时,我们再次调用syncData(),用后端数据的最新版本更新本地dynamic_cars变量。

注意:user_edited将被解析,因此您不必进行字符串比较,只需将其用作布尔变量。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70740463

复制
相关文章
Nvm 安装新的 nodejs 版本
在使用 nvm 安装新的 nvm 版本之前,请确定你的操作系统中已经安装了 nvm。
HoneyMoose
2021/08/11
3.2K0
Nvm 安装新的 nodejs 版本
Apache2 在Linux环境下的安装
在终端运行启动后,打开浏览器URL访问 http://localhost/ 或 127.0.0.1
Mirror王宇阳
2020/11/12
9870
appium新版本1.17安装后输入appium提示找不到
appium下载地址:https://cloud.189.cn/t/QRvInqzYzMNf(访问码:dq9x)
吾爱乐享
2020/05/21
7010
Ubuntu下如何安装apache2服务器
本篇内容主要讲解“Ubuntu下如何安装apache2服务器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Ubuntu下如何安装apache2服务器”吧!
会长君
2023/04/26
5850
linux apache2配置_apache2.4安装教程
大家好,又见面了,我是你们的朋友全栈君。 一、安装: ubuntu 及debian 下的apahce 有点特别,如果使用apt-get 方式安装( apt-get install apache2 ) 则安装目录默认在 /etc/apache2 默认log在 /var/log/apache2/ (这个鸟地方让我找了好久) 二、配置文件说明 /etc/apache2/apache2.conf 此为apache2 的主配置文件 具体可参考 http://www.blogjava.net/duanzhimin528/archive/2010/03/05/314564.html /etc/apache2/ports.conf 此为apache2的端口配置文件,此处设置了apache2 需要监听的端口 使用 Linsten port 格式 /etc/apache2/httpd.conf 此为apache2的用户 “主” 配置文件,这里可以直接配置网站目录,也可以只写一些全局网站生效的设置,eg:目录权限。默认为空,即所有内容由虚拟主机配置文件(即单独的网站配置文件)设置。需要注意一点 针对虚拟主机,ServerName 项需要在这里设置(不同的虚拟主机–即网站不同),可以写多个,否则在启动服务器的时候会提示:apache2: Could not reliably determine the server’s fully qualified domain name, using 127.0.1.1 for ServerName mods-available mods-enabled sites-available sites-enabled 以上几个目录作用见上文参考: 三、网站配置及多虚拟主机(网站) 此处可以分两种情况:第一 系统默认方式:即按照上面介绍的配置文件更改;第二 自定义修改方式; 假设我们需要添加一个新网站,端口8080 网站目录 /var/www/web_server2 方式一: 1、按照上面的说明配置: apache2.conf 不需要更改; ports.conf 添加 端口监听: NameVirtualHost *:8080 #此行不必须 Listen 8080 httpd.conf 添加 ServerName: ServerName 0.0.0.0:8080 #此处IP地址可以换成域名或者具体地址,ServerName 正常应该放到虚拟主机配置中,但实际测试发现不生效,必须写在这里; 配置虚拟主机(网站): cp sites-available/default sites-available/my_web_server2 #这里将默认的虚拟主机配置拷贝一份为my_web_server2(名字可以任取,建议和主机域名一致,不必和网站目录一致) 修改配置如下: NameVirtualHost *:8080 #此行不必须(默认是写在 ports.conf 中) <VirtualHost *:8080> ServerAdmin webmaster@localhost DocumentRoot /var/www/web_server2 #修改这里为实际网站目录 <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/web_server2/> #修改这里为实际网站目录 Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> …….. enable 网站: a2ensite my_web_server2 #my_web_server2 为sites-available/目录下的虚拟主机配置文件名(之前拷贝复制的) service apache2 reload sudo /etc/init.d/apache2 restart 确认网站启动: ls -l sites-enabled/ 有
全栈程序员站长
2022/10/02
2.1K0
apache2服务器_apache2配置
  摘要:在本地做WEB开发,同时多个项目,希望将每个项目都使用一个域名指向各自的项目根目录。要实现这样的目的,虚拟主机是必须要掌握的。本篇从一个小白用户的视角开始从零开始深入了解并实例配置演示。
全栈程序员站长
2022/10/02
2.2K0
探究新的 Solidity 0.8 版本
我们离 Solidity 1.0 的发布越来越近了(当然除非 0.9 之后是 0.10)。Solidity0.8[4]在0.7 发布[5]之后仅 5 个月就发布了!
Tiny熊
2021/02/25
1.5K0
探究新的 Solidity 0.8 版本
linux安装pycharm后找不到了_pycharmlinux安装
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/02
3.6K0
linux安装pycharm后找不到了_pycharmlinux安装
window 版本的安装
1 先解压 elasticsearch-7.3.0-windows-x86_64 安装包
用户5927264
2019/08/22
9100
ubuntu安装pycharm后找不到在哪_ubuntu安装类型
2、复制到虚拟机,并解压在当前文件夹,右键安装包,点击“Extract Here”
全栈程序员站长
2022/11/10
2.5K0
ubuntu安装pycharm后找不到在哪_ubuntu安装类型
VS code提示找不到git安装?
VS code是一个非常好用的工具,写代码利器。之前大部分都在Ubuntu上进行操作,也有在windows上操作,也没发现什么问题。VS code支持git(如下图)。所以在写代码的同时可以查看代码修改,这是一个非常舒服的操作。但是windows新的版本没有带git路径。
Rice加饭
2022/05/10
1.3K0
VS code提示找不到git安装?
linux安装pycharm后找不到了_ubuntu pycharm安装
pycharm 安装到linux(ubuntu、linuxmint) 先说本人使用的工作环境 win10家庭版 使用vmware 和vbox 两款虚拟机, ubuntu 16.04 linuxmint 一样的 废话少说。
全栈程序员站长
2022/11/02
2.6K0
apache2的几个核心设置优化
毕竟服务器的内存比较小,经常容易出现内存不足导致数据库退出等bug,so,除了设置swap缓冲区,最好的莫过于换成轻量级的服务器nginx,在那之前一些apache2服务器的优化也是比较必要的,so。
十四君
2019/11/23
1.8K0
Bridge CC 2022:数字资产管理的新境界+全版本安装包
Bridge CC 2022是Adobe公司推出的一款数字资产管理软件,旨在帮助用户更加高效地管理和组织数字素材。该软件支持各种文件格式,如图片、视频、音频、PDF等,提供了强大的检索和筛选功能,使用户可以轻松地快速找到所需的文件。同时,Bridge CC 2022还提供了许多实用的工具,如批处理、加标记、预览、批量输出等,大大提高了工作效率。
用户10480228
2023/04/16
3130
Bridge CC 2022:数字资产管理的新境界+全版本安装包
Apache2(http.2.4.6) + Tomcat 7.0 集群安装与配置
最近由于工作需要,公司需要部署 tomcat 集群,忙活了几天,终于配置了好了,做个笔记以后备用。
星哥玩云
2022/06/28
8260
Python版本的OpenCV安装
https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/
MiChong
2020/09/24
1.5K0
安装老版本的Pytorch
We’d prefer you install the latest version, but old binaries and installation instructions are provided below for your convenience.
狼啸风云
2021/02/04
7.7K0
mac Python安装pybloomfilter 出现找不到libcrypto的问题
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/148523.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/07
5350
apache2开启SSL
windows+apache2开启SSL以及80端口强制跳转SSL访问的方法 申请证书 推荐Let’s Encrypt(免费证书的有效期为3个月,但提供了自动更新证书的功能) 开启ssl模块 首先确保apache开启了LoadModule ssl_module modules/mod_ssl.so 配置443端口 再参考官方文档的一段内容: Listen 443 <VirtualHost *:443> DocumentRoot "项目入口文件目录" ServerName 域名 SSL
lestat
2018/04/17
2.6K0
点击加载更多

相似问题

如果满足某些条件,则从元组列表中删除元组。

62

如果满足某些条件,则从包含元组列表的列表中删除元组。

30

如果元素出现在字符串列表中,则从元组列表中获取元组。

14

根据给定的准则从元组列表中删除元组

31

从元组列表中组合元组元素。元组元素是元组和列表。

22
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文