使用来自榆树的 bootstrap-select
Using bootstrap-select from elm
我正在尝试使用 bootstrap-select - 一个扩展 html-select 标签的 javascript/css 库,具有很好的特性和风格。乍一看,从 elm 调用它似乎很简单。确实,被剪断了
view : Model -> Html Msg
view model =
select [ class "selectpicker", attribute "data-live-search" "true" ]
[ option [] [ text "foo" ]
, option [] [ text "bar" ]
]
生成一个漂亮的(可搜索的)select 框,其中包含两个项目。然而,在动态情况下事情会变得复杂。假设我们的榆树模型是一个布尔值,决定 select 框是否显示。
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" ]
加载页面时,我们再次看到一个漂亮的 select 框,当点击切换按钮时它会消失。然而,当再次点击 toogle 按钮时,select 框将不会再次出现!原因是selectpicker节点如果内容发生变化需要刷新(包括enabling/disabling节点)。也就是说,我们要调用
$('.selectpicker').selectpicker('refresh');
来自外部 Javascript 世界 在 我们的 select 盒子再次添加到 DOM 之后。
我尝试使用端口解决该问题,但不幸的是我只让 elm 在 渲染之前 触发一个事件,所以我还必须使用 setTimeout
来等待完成,这很hacky。我想一定有一个使用自定义元素的巧妙解决方案,但同样,我无法弄清楚如何在正确的时刻调用刷新函数。
非常感谢任何帮助!
最后,我设法将 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 一堆选项还是一堆选项组)。
我很乐意看到更好的解决方案,但由于这是另一个话题,我将很快开始跟进问题。
我正在尝试使用 bootstrap-select - 一个扩展 html-select 标签的 javascript/css 库,具有很好的特性和风格。乍一看,从 elm 调用它似乎很简单。确实,被剪断了
view : Model -> Html Msg
view model =
select [ class "selectpicker", attribute "data-live-search" "true" ]
[ option [] [ text "foo" ]
, option [] [ text "bar" ]
]
生成一个漂亮的(可搜索的)select 框,其中包含两个项目。然而,在动态情况下事情会变得复杂。假设我们的榆树模型是一个布尔值,决定 select 框是否显示。
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" ]
加载页面时,我们再次看到一个漂亮的 select 框,当点击切换按钮时它会消失。然而,当再次点击 toogle 按钮时,select 框将不会再次出现!原因是selectpicker节点如果内容发生变化需要刷新(包括enabling/disabling节点)。也就是说,我们要调用
$('.selectpicker').selectpicker('refresh');
来自外部 Javascript 世界 在 我们的 select 盒子再次添加到 DOM 之后。
我尝试使用端口解决该问题,但不幸的是我只让 elm 在 渲染之前 触发一个事件,所以我还必须使用 setTimeout
来等待完成,这很hacky。我想一定有一个使用自定义元素的巧妙解决方案,但同样,我无法弄清楚如何在正确的时刻调用刷新函数。
非常感谢任何帮助!
最后,我设法将 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 一堆选项还是一堆选项组)。
我很乐意看到更好的解决方案,但由于这是另一个话题,我将很快开始跟进问题。