Использование bootstrap -выбор от вяза - PullRequest
0 голосов
/ 03 мая 2020

Я пытаюсь использовать bootstrap -select - библиотеку javascript / css, расширяющую тег html -select приятными функциями и стилем. На первый взгляд, назвать его из вяза кажется простым. Действительно, урезанный

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

дает красивое (доступное для поиска) поле выбора с двумя элементами. Однако, все усложняется в динамических c ситуациях. Предположим, что наша модель вяза является логическим, решающим, показывать или нет окно выбора.

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" ]

При загрузке страницы мы снова видим красивое окно выбора, которое исчезает при нажатии кнопки переключения. Однако при повторном нажатии кнопки переключателя окно выбора снова не появится! Причина в том, что узлы selectpicker должны обновляться, если содержимое изменилось (включая включение / отключение узла). То есть мы должны позвонить

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

извне Javascript world после наше поле выбора было снова добавлено в DOM.

Я пытался решить эту проблему с помощью портов, но, к сожалению, я получил только elm для запуска события перед рендерингом, поэтому мне пришлось дополнительно использовать setTimeout, чтобы дождаться завершения, что довольно странно. Я полагаю, что должно быть изящное решение с использованием пользовательского элемента, но, опять же, я не смог понять, как вызвать функцию refre sh в нужный момент.

Любая помощь очень ценится!

1 Ответ

1 голос
/ 03 мая 2020

Наконец, мне удалось обернуть bootstrap -выбрать в (минимальный, не идеальный) пользовательский элемент, который автоматически обновляется при обновлениях. Вот он:

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>

или из elm как

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

, и он также работает в Dynami c ситуации, как указано выше. Однако очевидным недостатком является то, что список элементов должен быть задан атрибуту lit-select, закодированному в виде строки json. Таким образом, возможности разметки довольно ограничены (например, пользователь не может решить, будет ли он выделен набором опций или набором опций).

Я был бы рад увидеть лучшие решения, но так как это это еще одна топика c, я скоро начну следующий вопрос.

...