【问题标题】:Using bootstrap-select from elm使用来自榆树的引导选择
【发布时间】:2020-05-03 10:27:46
【问题描述】:

我正在尝试使用bootstrap-select - 一个扩展 html-select-tag 的 javascript/css 库,具有很好的功能和样式。乍一看,从 elm 调用它似乎很简单。确实,被剪掉了

view : Model -> Html Msg
view model =
  select [ class "selectpicker", attribute "data-live-search" "true" ]
    [ option [] [ text "foo" ]
    , option [] [ text "bar" ]
    ]

产生一个带有两个项目的漂亮(可搜索)选择框。但是,在动态情况下事情会变得复杂。假设我们的 elm 模型是一个布尔值,决定是否显示选择框。

type alias Model = Bool

init : Model
init = True

update : Msg -> Model -> Model
update Toggle model = not model

view : Model -> Html Msg
view model =
  if model then
    div []
    [ select [ class "selectpicker", attribute "data-live-search" "true" ]
        [ option [] [ text "foo" ]
        , option [] [ text "bar" ]
        ]
    , button [ onClick Toggle ] [ text "toggle" ]
    ]
    else
      button [ onClick Toggle ] [ text "toggle" ]

加载页面时,我们再次看到一个漂亮的选择框,当点击切换按钮时它会消失。但是,当再次点击togle按钮时,选择框不会再次出现!原因是如果内容发生更改(包括启用/禁用节点),则需要刷新 selectpicker 节点。也就是我们要调用

$('.selectpicker').selectpicker('refresh');

从外部 Javascript 世界我们的选择框再次添加到 DOM 中。

我尝试使用端口来解决这个问题,但不幸的是,我只有在 渲染之前让 elm 触发一个事件,所以我还不得不使用 setTimeout 等待完成,这很 hacky .我想一定有一个使用自定义元素的巧妙解决方案,但是我还是不知道如何在适当的时候调用刷新函数。

非常感谢任何帮助!

【问题讨论】:

  • 这似乎是 a web component 的教科书示例
  • @glennsl 谢谢你的提示!如果我理解正确,这意味着我必须先将 selectpicker 库包装到 web 组件中?
  • 是的,除非你很幸运,它已经附带了一个,或者其他人已经制作了一个。
  • @glennsl 不幸的是,我已经尝试过这种方法并最终失败了。所以无论如何,我需要进一步的建议..
  • 在某些极端情况下,您还需要在自定义元素的 connectedCallback 中添加 setTimeout。所以自定义元素可能不值得。

标签: javascript elm custom-element bootstrap-select bootstrap-selectpicker


【解决方案1】:

最后,我设法将 bootstrap-select 包装到一个(最小的、不完美的)自定义元素中,该元素会在更新时自动刷新。这里是:

import { LitElement, html, customElement, property } from 'lit-element';
import * as $ from 'jquery';
import 'bootstrap';
import 'bootstrap-select';

@customElement('lit-select')
export class LitSelect extends LitElement {

    @property({ type : Array }) items = []

    updated() {
        $(this).find(".selectpicker").selectpicker('refresh');
    }

    createRenderRoot() {
        return this;
    }

    private renderItem(item: string) {
        return html`
            <option>
                ${item}
            </option>
        `;
    }

    render() {
        return html`
            <select class="selectpicker" data-live-search = "true">
                ${this.items.map(item => this.renderItem(item))}
            </select>
        `;
    }
}

这个元素可以从 HTML 创建为

<lit-select items='["foo", "bar"]'></lit-select>

或来自榆树

node "lit-select" [ attribute "items" "[\"foo\",\"bar\"]" ] []

它也适用于上述动态情况。 但是,一个明显的缺点是项目列表必须提供给编码为 json 字符串的 lit-select 属性。所以标记的可能性是相当有限的(例如,用户无法决定是给 lit-select 一堆选项还是一堆选项组)。

我很高兴看到更好的解决方案,但由于这是另一个主题,我将很快提出后续问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多