Skip to content

Commit

Permalink
feat: Add Rich MultiSelect functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
staylorwr committed Jan 20, 2022
1 parent fd9cd6d commit 7c39bf7
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 3 deletions.
32 changes: 30 additions & 2 deletions assets/src/components/Detail/MultiSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,37 @@
<span
v-for="v in field.value"
:key="v.value"
class="inline-block mr-2 bg-gray px-2 py-1"
class="inline-block mr-2 border border-rounded-sm px-2 py-1"
>
{{ v.label }}
<div
v-if="v.title"
slot="default"
class="flex items-center"
>
<div
v-if="v.thumbnail"
class="mr-3"
>
<img
:src="v.thumbnail"
class="w-6 h-6 rounded block"
>
</div>
<div class="flex">
<p class="text-gray-darkest mr-2">
{{ v.title }}
</p>
<p
v-if="v.subtitle"
class="text-xs mt-1 opacity-75"
>
{{ v.subtitle }}
</p>
</div>
</div>
<span v-else>
{{ v.label }}
</span>
</span>
</p>
</panel-item>
Expand Down
76 changes: 76 additions & 0 deletions assets/src/components/Form/MultiSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,76 @@
>
<template slot="field">
<Multiselect
v-if="useCards"
v-model="value"
:options="options"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
:preselect-first="true"
placeholder="Pick some"
label="label"
track-by="value"
>
<template slot="tag" slot-scope="{ option, remove }">
<div class="inline-flex items-center mr-2 border rounded px-2 py-1 mb-2">
<div
v-if="option.thumbnail"
class="mr-3"
>
<img
:src="option.thumbnail"
class="w-8 h-8 rounded block"
>
</div>
<div>
<p class="text-gray-darkest">
{{ option.title }}
</p>
<p
v-if="option.subtitle"
class="text-xs mt-0.5 opacity-75"
>
{{ option.subtitle }}
</p>
</div>
<a @click="remove(option)" class="w-5 h-5 rounded-full block border border-danger text-danger flex items-center justify-center ml-4">
<icon
type="delete"
:width="12"
:height="12"
/>
</a>
</div>
</template>
<template slot="option" slot-scope="props">
<div class="inline-flex items-center">
<div
v-if="props.option.thumbnail"
class="mr-3"
>
<img
:src="props.option.thumbnail"
class="w-8 h-8 rounded block"
>
</div>
<div>
<p class="text-gray-darkest">
{{ props.option.title }}
</p>
<p
v-if="props.option.subtitle"
class="text-xs mt-0.5 opacity-75"
>
{{ props.option.subtitle }}
</p>
</div>
</div>
</template>
</Multiselect>
<Multiselect
v-else
v-model="value"
:options="options"
:multiple="true"
Expand Down Expand Up @@ -33,6 +103,12 @@ export default {
options: []
}),
computed: {
useCards () {
return !!this.field.options[0].title;
}
},
mounted () {
this.value = this.field.value || false;
this.options = this.field.options;
Expand Down
26 changes: 25 additions & 1 deletion lib/ex_teal/fields/multi_select.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,43 @@ defmodule ExTeal.Fields.MultiSelect do
MultiSelect.make(:regions)
|> MultiSelect.with_options([%{value: 1, label: "USA"}, %{value: 2, label: "EU"}])
You can also return a list of maps with `value`, `title`, `subtitle` and `thumbnail` keys
to use 'card' style taggables, useful when the multiselect represents a relationship.
"""

@type simple_option :: %{
value: :integer | String.t(),
label: String.t()
}

@type card_option :: %{
required(:value) => :integer | String.t(),
required(:title) => String.t(),
optional(:subtitle) => String.t(),
optional(:thumbnail) => String.t()
}

@type valid_option :: simple_option | card_option

@type valid_options :: list(valid_option)

use ExTeal.Field
alias ExTeal.Field

def component, do: "multi-select"

def default_sortable, do: false

@spec with_options(Field.t(), valid_options | (() -> valid_options)) :: Field.t()
def with_options(field, options) when is_list(options) do
%{field | options: options, private_options: %{display_using_labels: false}}
%{field | options: options}
end

def with_options(field, options_fn) when is_function(options_fn) do
IO.warn(
"with_options/2 callback is depreciated, and will be removed in 1.0. See `ExTeal.Fields.MultiSelect.with_options/2`"
)

options = options_fn.()
with_options(field, options)
end
Expand Down

0 comments on commit 7c39bf7

Please sign in to comment.