宜搭——下拉单选

最近,花了一周时间用宜搭做了个Web工具。中间遇到很多坑,还好宜搭的文档不错,除了基本的功能使用开发介绍外,还有很多专题案例,基本上可以找到答案,或从中得到灵感。选用宜搭的原因,除了团队最近在使用,主要还是因为它是低代码,可迅速搭建界面,开发语言是js,非常容易上手。

1 必备

先把个人觉得非常重要的文档和常用快捷键,放上来:

1.1 文档

1.2 快捷键

在写js代码时,肯定要快捷键,好像跟vscode的快捷键一样。这几个是我经常使用的

快捷键说明
复制行到上或下⇧ + ⌥ + ↑[或↓]
向上或下移动当前行⌥ + ↑[或↓]
多行选择⇧ + ⌥ + 光标选择
删除行⇧ + ⌘ + K
向后搜索并添加到选择中(批量修改)⌘ + D

2 下拉单选

表单自定义页面,都有下拉单选组件,表单中叫“下拉单选”,自定义页面叫“下拉选择”,两者功能都一样,只是在不同页面中的不同叫法而已。

下面由表入里,讲述它的使用

2.1 设置显示状态

// NORMAL:正常显示,DISABLED:禁用,READONLY:只读,HIDDEN:隐藏
this.$("selectField_kvnwz0n2").setBehavior("READONLY")
// 或
this.$("selectField_kvnwz0n2").set("behavior", "READONLY")

2.2 设置占位符placeholder

this.$("selectField_kvnwz0n2").set("placeholder", "请选择地区")

2.3 设置下拉选项

  this.$("selectField_kvnwz0n2").set("dataSource", [{
      text: '中国',
      value: '中国'
    },
    {
      text: '日本',
      value: '日本'
    },
    {
      text: '韩国',
      value: '韩国'
    }
  ])

text对应的是显示值;value是组件值,即this.$("selectField_kvnwz0n2").getValue()

tips:如果还想保存其它信息,比如首都,都可以往里塞。可以通过动作export function onChange({value, actionType, item})的item获取

2.4 获取下拉选项

this.$("selectField_kvnwz0n2").cachedDataSource
// 或
this.$("selectField_kvnwz0n2").getProps().dataSource

2.5 设置值

this.$("selectField_kvnwz0n2").setValue("中国")

2.6 获取值

this.$("selectField_kvnwz0n2").getValue()

2.7 子表单中的下拉单选

先看下我们要实现的效果:
子表单中的首都项和城市项,默认READONLY。当选择国家后,首都自动填入;城市根据所选国家,一把占位提示改成“选择{国家}城市”,然后把该国的部分城市更新到下拉选项中供选择
在这里插入图片描述

很多时候,我们需要处理子表单中的下拉单选。有些功能通过上述方式无法实现。来,上菜:

  • 状态组件值,还是可以通过原方式setBehavior()和setValue()来设置
  • placeholderdataSource,得通过来setComponentProps()来设置了

说明set("placeholder", yourPlaceHolder)set("dataSource", yourOptions),有时也可以在动作(如:onChange)中使用,但第一表单的第一行里设置无效。实在要用,可以在页面最前面加个隐藏、不提交数据的子表单也行。但为了安全起见,不推荐使用

2.7.1 状态和值
/**
 * 当子菜单的国家选择之后执行
 */
export function onSubNationChange({value, actionType, item}) {
  console.log('onSubNationChange', value);
  const cityField = this.$(sub_single_city_id)
  cityField.setValue("")
  if(typeof value == "undefined"){
    cityField.setBehavior("READONLY")
    return
  }
  cityField.setBehavior("NORAML")
}

在子菜单同一行的动作中,如onChange(),可以直接通过this.$()来获取本行中的其它组件。正如上述代码所示,可以直接获取本行的城市组件。如果在其他位置,获取的就是一个组件数组了

setValue()其实有个坑,往下看

2.7.2 占位符和下拉选项

先了解下这个方法,它是用来设置子表单中某个组件的属性
tableField.setComponentProps(groupId, fieldId, data)

  • groupId:条目id,也就是所在行的id,eg:tfitem_3。通过tableField.getItems()可获取所有条目id
  • fieldId: 组件id
  • data:属性值
export function onSubNationChange({value, actionType, item}) {
  console.log('onSubNationChange', value);
  const cityField = this.$(sub_single_city_id)
  cityField.setValue("")
  if(typeof value == "undefined"){
    cityField.setBehavior("READONLY")
    return
  }
  cityField.setBehavior("NORAML")

  // 获取当前item的groupId
  const groupId = this.$(sub_single_nation_id).formGroupId
  table_field.setComponentProps(groupId, sub_single_city_id, {
    placeholder: "选择" + value + "城市",
    dataSource: item.cities.map(it => {
      return {
        text: it,
        value: it
      }
    })
  })
}

上述代码中,如果直接通过组件设置,那第一个表单的第一行将无效。可以试试看,后半部分的代码改成如下:

  cityField.setBehavior("NORAML")
  
  // 直接通过组件设置(不推荐)
  cityField.set("placeholder", "选择" + value + "城市")
  cityField.set("dataSource", item.cities.map(it => {
      return {
        text: it,
        value: it
      }
    })
  )
2.7.3 setValue()无效?

现在,我们在onChange()中不直接设置,而是先通过从其它表单中查找数据,再设置:

export function onSubNationChange({value, actionType, item}) {
  ...省略...

  // 首都
  const capitalField = this.$(sub_single_capital_id)
  // capitalField.setValue(item.capital)
  const params = {
    formUuid: "FORM-2O86******01",
    searchFieldJson: JSON.stringify({
      textField_kvp2qxo7: value
    })
  }
  this.dataSourceMap['searchFormDatas'].load(params).then(resp => {
    console.log("searchCaptical=" + JSON.stringify(resp))
    let capital
    if (resp.data.length > 0) {
      capital = resp.data[0].formData.textField_kvp2qxo8
    }
    console.log("arr", capital)
    // capitalField.setValue(capital)
    const groupId = this.$(sub_single_nation_id).formGroupId
    table_field.setComponentProps(groupId, sub_single_capital_id, {value: capital})
  })
  ...省略...
}

我们把首都设置为必填。在提交表单时,发现报错了:
必填
明明已经设置进去了,都显示了,怎么还报错了?如果不设置必填,查看数据时会发现,此项为空。除非手动填入
尝试过table_field.setComponentProps(groupId, sub_single_capital_id, {value: capital}),也不行

向上找思路,就是通过子表单来完成,子表单有setValue(),我们通过这个方法来迂回解决。但要注意子表单还要其它数据,所以只能更新首都项的数据。这样更新,虽然数据正确了,但不会显示,所以还得加上capitalField.setValue(capital)

	this.dataSourceMap['searchFormDatas'].load(params).then(resp => {
    console.log("searchCaptical=" + JSON.stringify(resp))
    let capital
    if (resp.data.length > 0) {
      capital = resp.data[0].formData.textField_kvp2qxo8
    }
    console.log("capital", capital)
    const tbVal = table_field.getValue()
    console.log("table old value", tbVal)
    tbVal[itemIndex].selectField_kvnwz0n8 = capital
    table_field.setValue(tbVal)
    capitalField.setValue(capital)
  })

其中,子表单的数据格式如下:
在这里插入图片描述

要是有更好的方法,麻烦告知,感谢!

3 附录

3.1 数据源

数据源 ### 3.2 js源码 > demo演示源码,非工具源码(公司的,不能公开)
/**
 * 下拉单选_表单案例
 * @author Ralap
 * @date 2021-11-07
 */

const countries = [{
    text: '中国',
    value: '中国',
    capital: '北京',
    cities: [
      "北京",
      "上海",
      "杭州",
      "广州",
      "深圳"
    ]
  },
  {
    text: '日本',
    value: '日本',
    capital: '东京',
    cities: [
      "东京",
      "大阪",
      "横滨",
      "名古屋"
    ]
  },
  {
    text: '韩国',
    value: '韩国',
    capital: '首尔',
    cities: [
      "首尔",
      "釜山",
      "济州"
    ]
  }
]

let outer_single_field
let outer_text_field
let table_field

const sub_single_nation_id = 'selectField_kvnwz0n5'
const sub_single_city_id = 'selectField_kvnwz0n6'
const sub_single_capital_id = 'selectField_kvnwz0n8'

export function didMount() {
  console.log(`「页面 JS」:当前页面地址 ${location.href}`)
  this.initFields()
}

export function initFields() {
  outer_single_field = this.$("selectField_kvnwz0n2")
  outer_text_field = this.$("textField_kvnwz0n3")
  table_field = this.$("tableField_kvnwz0n4")

  outer_single_field.set("placeholder", "请选择国家")
  outer_single_field.set("dataSource", countries)

  // 初始化子表单的第一行
  const latestIndex = table_field.getItems().length - 1
  const groupName = table_field.getItems()[latestIndex]
  table_field.setComponentProps(groupName, sub_single_nation_id, {
    placeholder: "请选择国家_sub",
    dataSource: countries
  })
  // 第一行也可以通过这样来赋值
  // this.$(sub_single_nation_id)[0].set("placeholder", "请选择国家_sub")
  // this.$(sub_single_nation_id)[0].set("dataSource", countries)
}

export function onOuterNationChange({ value, actionType, item }) {
  console.log('onOuterNationChange: value', value);
  console.log('onOuterNationChange: actionType', actionType);
  console.log('onOuterNationChange: item', item);
  console.log("dataSource1:", outer_single_field.getProps().dataSource)
  console.log("dataSource2:", outer_single_field.cachedDataSource)
  outer_text_field.setValue(item.capital)
}

/**
 * 当子菜单的国家选择之后执行
 */
export function onSubNationChange({value, actionType, item}) {
  console.log('onSubNationChange', value);
  const cityField = this.$(sub_single_city_id)
  cityField.setValue("")
  if(typeof value == "undefined"){
    cityField.setBehavior("READONLY")
    return
  }
  cityField.setBehavior("NORAML")

  // 首都
  const capitalField = this.$(sub_single_capital_id)
  // capitalField.setValue(item.capital)
  const itemIndex = table_field.getItems().indexOf(capitalField.formGroupId)
  const params = {
    formUuid: "FORM-2O86******01",
    searchFieldJson: JSON.stringify({
      textField_kvp2qxo7: value
    })
  }
  this.dataSourceMap['searchFormDatas'].load(params).then(resp => {
    console.log("searchCaptical=" + JSON.stringify(resp))
    let capital
    if (resp.data.length > 0) {
      capital = resp.data[0].formData.textField_kvp2qxo8
    }
    console.log("capital", capital)
    const tbVal = table_field.getValue()
    console.log("table old value", tbVal)
    tbVal[itemIndex].selectField_kvnwz0n8 = capital
    table_field.setValue(tbVal)
    // 加上,才能显示
    capitalField.setValue(capital)
  })

  // 获取当前item的groupId
  const groupId = this.$(sub_single_nation_id).formGroupId
  table_field.setComponentProps(groupId, sub_single_city_id, {
    placeholder: "选择" + value + "城市",
    dataSource: item.cities.map(it => {
      return {
        text: it,
        value: it
      }
    })
  })

  // set()方式设置,有缺陷
  // cityField.set("placeholder", "选择" + value + "城市")
  // cityField.set("dataSource", item.cities.map(it => {
  //   return {
  //     text: it,
  //     value: it
  //   }
  // })
  // )
}

/**
* TableField onAddClick
*/
export function onSubAddClick(newGroupId){
  console.log('onSubAddClick');
  // 子表单添加一项后,对其初始化。
  // 这里还不能通过this.$(sub_single_nation_id)找到
  const latestIndex = table_field.getItems().length - 1
  const groupName = table_field.getItems()[latestIndex]
  table_field.setComponentProps(groupName, sub_single_nation_id, {
    placeholder: "请选择国家_sub",
    dataSource: countries
  })
}
  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值