layui 远程搜索下拉选择组件(多选)

news/2025/2/21 10:01:04

模板使用(lay-module/searchSelect),依赖于 jquery、layui.dist 中的 dropdown 模块实现(所以data 格式请参照 layui文档)

<link rel="stylesheet" href="layui-v2.5.6/dist/css/layui.css" />
<link rel="stylesheet" href="lay-module/searchSelect/index.css" />

<form id="app-form" class="layui-form layuimini-form">
	<div class="layui-form-item">
      <label class="layui-form-label">测试</label>
      <div class="layui-input-block search-select-component">
        <!-- data-init以title字段作为显示 -->
        <input name="tags" data-init='[{"id":1,"title":"123"}]' placeholder="Search..." class="layui-input search-select-input" />
      </div>
    </div>
    <div class="layui-form-item">
      <button type="submit" class="layui-btn" lay-submit lay-filter="demo-submit">确认</button>
      <button type="reset" class="layui-btn">重置</button>
    </div>
</form>

<script src="jquery.min.js"></script>
<script src="layui-v2.5.6/dist/layui.js"></script>
<script src="lay-module/searchSelect/index.js"></script>
<script>javascript">
layui.use(['jquery','form'], function () {
    const $ = layui.jquery;
    const form = layui.form;
    
    // 搜索下拉选择组件处理方法(默认拾取元素 elem: '.search-select-input')
	layui.searchSelect.render({
      onSearch: function (search) {
        console.log('onSearch', search);
        $.ajax({
          url: '/api/gelist',
          type: 'GET',
          data: {
            key: search.name,
            val: search.value,
          },
          dataType: 'json',
          success: function (res) {
            if (res.code == 1) {
              // res.data 中的 "title字段" 作为显示名称
              search.update(res.data);
            } else {
              layer.msg(res.msg, { icon: 2 });
            }
          },
          error: function () {
            layer.msg('network error', { icon: 2 });
          },
        });
      },
    });

	// 表单提交处理
	form.on('submit(demo-submit)', function(data){
		// 使用 layui.searchSelect.getValue 获取所有 searchSelect 值,传入 name 可以只取对应的value
		// 对应的value也会设置到对应的 .search-select-input 的 data-val 中
		const dd = layui.searchSelect.getValue();
		console.log(data, dd)
	});
});
</script>

searchSelect 模块实现(lay-module/searchSelect 目录中添加以下 index.js、index.css 文件)

1、index.css

.search-select-component .tags.select-list {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
  margin-bottom: 20px;
  border: none;
}

.search-select-component .tags.select-list:empty {
  margin-top: 0;
  margin-bottom: 0;
}

.search-select-component .select-list-item {
  position: relative;
  padding-right: 20px;
  padding-top: 2px;
}

.search-select-component .select-list-item .name {
  font-size: 14px;
}

.search-select-component .select-list-item .del {
  position: absolute;
  top: 0;
  right: 0;
  font-size: 30px;
  font-weight: normal;
  line-height: 20px;
  float: none;
  width: 18px;
  padding: 0;
  cursor: pointer;
  text-align: center;
  opacity: 1;
  color: #ea0000;
  border: 0 none;
  background: transparent none repeat scroll 0 0;
  text-shadow: none;
}

.search-select-component .layui-layer-msg {
  top: 40% !important;
}

2、index.js 文件

javascript">/*
 * @Author: mojon
 * @Date:   2025-02-19 11:40:42
 * @Last Modified by:   hi916
 * @Last Modified time: 2025-02-19 15:52:33
 * @Last Modified description: 搜索下拉选择组件(多选)
 */
layui.define(['jquery', 'dropdown'], function (exports) {
  'use strict';
  const $ = layui.jquery;
  const dropdown = layui.dropdown;

  // 绑定值
  let values = {};

  // 删除item
  function delItem(event) {
    const name = $(event.target).data('name');
    const value = $(event.target).data('value');
    console.log('删除item', name, value);

    if (values[name]) {
      values[name] = values[name].filter((item) => JSON.stringify(item) != JSON.stringify(value));
      $(event.target).parent().remove();
      $(event.target).data('val', values[name]);
    }
  }

  // 添加item
  function addItem(el, value) {
    const name = $(el).attr('name');
    values[name].push(value);
    $(el).data('val', values[name]);

    console.log('添加item', name, values[name]);

    // item容器
    const div = document.createElement('div');
    div.classList.add('select-list-item');

    // title显示 (以title字段作为显示)
    const span = document.createElement('span');
    span.classList.add('name');
    span.textContent = value.title;

    // del按钮
    const btn = document.createElement('button');
    btn.classList.add('del');
    btn.textContent = 'x';
    btn.setAttribute('type', 'button');
    btn.setAttribute('data-name', name);
    btn.setAttribute('data-value', JSON.stringify(value));
    // 监听删除事件
    btn.addEventListener('click', delItem);

    div.appendChild(span);
    div.appendChild(btn);

    $(el).siblings('.tags.select-list').append(div);

    // $(el).siblings('.tags.select-list').append(`
    //     <div class="select-list-item">
    //       <span class="name">${data.title}</span>
    //       <button type="button" class="del">×</button>
    //     </div>
    // `);
  }

  // 监听选择
  function onSelect(el) {
    // 插入选择存放位置
    $(el).after('<div class="tags select-list"></div>');
    // 获取配置
    const name = $(el).attr('name');
    const width = $(el).width();
    const dropdown = layui.dropdown;
    const dropdownHeight = 300;
    dropdown.render({
      elem: el,
      id: name,
      position: 'absolute', // 设置位置为相对
      data: [],
      style: `
          max-height: ${dropdownHeight}px;
          width: ${width}px;
          overflow-y: auto;
          overflow-x: hidden;
      `,
      click: function (obj) {
        if (values[name]) {
          const isInclude = values[name].find((item) => JSON.stringify(item) == JSON.stringify(obj));
          // 没有重复选择
          if (!isInclude) addItem(el, obj);
        }
      },
    });
  }

  // 更新下拉选择列表
  function updateDropdown(name, data) {
    dropdown.reload(name, { data, show: true });
  }

  // 监听执行搜索
  function onSearch(el, callback = () => {}) {
    let timer = null;
    $(el).on('input', function (e) {
      const val = $(this).val();
      const data = $(this).data();
      const name = $(el).attr('name');
      clearTimeout(timer);
      timer = setTimeout(() => {
        if (val) {
          console.log('搜索onSearch', val);
          callback({
            ...data,
            name: name,
            value: val,
            update: (data) => updateDropdown(name, data),
          });
        }
      }, 500);
    });
  }

  // 初始化(处理初始状态显示)
  function init(el) {
    const name = $(el).attr('name');
    const initValues = $(el).data('init');
    if (initValues) {
      initValues.forEach((value) => addItem(el, value));
    }
    console.log('初始化init', name, values);
  }

  // 获取值
  function getValue(name) {
    if (name) {
      return values[name];
    } else {
      return values;
    }
  }

  // 加载配置
  function render(options) {
    // 配置
    const opt = {
      elem: '.search-select-input',
      onSearch: () => {},
      ...options,
    };

    // 遍历所有 searchSelect
    $(opt.elem).each((index, el) => {
      const name = $(el).attr('name');
      if (name) {
        // 生成预处理值
        values[name] = [];
        // 监听选择
        onSelect(el);
        // 监听搜索
        onSearch(el, opt.onSearch);
        // 初始化处理
        init(el);
      }
    });
  }

  // 组件初始化
  function Component() {
    return {
      render: render,
      getValue: getValue,
    };
  }

  exports('searchSelect', new Component());
});


http://www.niftyadmin.cn/n/5860655.html

相关文章

机器学习实战(9):神经网络基础——从感知机到多层感知机

机器学习中的神经网络部分是大模型LLM训练的基础之基础&#xff0c;熟练掌握这一部分的知识和基础技能对后续理解大模型原理至关重要&#xff01; 第9集&#xff1a;神经网络基础——从感知机到多层感知机 在机器学习中&#xff0c;神经网络&#xff08;Neural Networks&#…

矩阵加减乘除的意义与应用

矩阵加法 数学意义 线性空间的封闭性线性变换的叠加矩阵分解与表示 实际应用 数据聚合与统计图像处理与计算机视觉物理学与工程学动态系统与优化经济学与运筹学信号处理与通信游戏开发与计算机图形学环境科学与地理信息矩阵加法的关键特点 矩阵减法 数学意义线性空间封闭性 线…

汽车前排座椅扶手市场报告:未来几年年复合增长率CAGR为2.7%

汽车扶手是一种安装在两个座椅中间的汽车配件&#xff0c;隶属于汽车内饰系统。其人性化的设计初衷是为了使汽车驾驶员在长时间驾驶时能够放置胳膊&#xff0c;从而能够使胳膊得到有效的休息不至于酸麻、僵硬。随着制造技术的不断发展&#xff0c;生产工艺的不断改良&#xff0…

【项目实践07】【多线程下事务的一致性】

文章目录 一、前言二、项目背景三、实现方案四、思路延伸1. 方案一2. 方案二3. 方案三 五、参考内容 一、前言 本系列用来记录一些在实际项目中的小东西&#xff0c;并记录在过程中想到一些小东西&#xff0c;因为是随笔记录&#xff0c;所以内容不会过于详细。 本篇从开篇到完…

一周学会Flask3 Python Web开发-response响应格式

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在HTTP响应中&#xff0c;数据可以通过多种格式传输。大多数情况下&#xff0c;我们会使用HTML格式&#xff0c;这也是Flask中…

DeepSeek赋能智慧文旅:新一代解决方案,重构文旅发展的底层逻辑

DeepSeek作为一款前沿的人工智能大模型&#xff0c;凭借其强大的多模态理解、知识推理和内容生成能力&#xff0c;正在重构文旅产业的发展逻辑&#xff0c;推动行业从传统的经验驱动向数据驱动、从人力密集型向智能协同型转变。 一、智能服务重构&#xff1a;打造全域感知的智…

解锁机器学习核心算法|神经网络:AI 领域的 “超级引擎”

一、神经网络&#xff1a;AI 领域的 “超级引擎” 在机器学习的庞大算法体系中&#xff0c;有十种算法被广泛认为是最具代表性和实用性的&#xff0c;它们犹如机器学习领域的 “十大神器”&#xff0c;各自发挥着独特的作用。这十大算法包括线性回归、逻辑回归、决策树、随机森…

ARM64 Trust Firmware [四]

完成第二阶段 BL2 的操作后就加载并进入 BL31&#xff0c;BL31 位于 DRAM 中&#xff0c;EL3 模式。除了做架构初始化和平台初始化外&#xff0c;还做了如下工作&#xff1a; 基本硬件初始化&#xff0c;比如 GIC&#xff0c;串口&#xff0c;timer 等&#xff1b;PSCI 服务的…