Testing list items by passing down a event handler through context for selecting items

This commit is contained in:
Conor Mack 2020-02-27 10:03:49 +00:00
parent 62e562c1f1
commit d88d377f5f
7 changed files with 92 additions and 70 deletions

View File

@ -1,5 +1,5 @@
<script>
import { onMount, onDestroy, getContext } from "svelte"
import { onMount, onDestroy } from "svelte"
import Formfield from "../Common/Formfield.svelte"
import { fieldStore } from "../Common/FormfieldStore.js"
import ClassBuilder from "../ClassBuilder.js"
@ -7,6 +7,8 @@
export let onClick = item => {}
export let _bb
export let id = ""
export let label = ""
export let disabled = false
@ -16,16 +18,18 @@
let instance = null
let checkbox = null
let context = getContext("BBMD:input:context")
let context = null
onMount(() => {
context = _bb.getContext("BBMD:input:context")
if (!!checkbox) {
instance = new MDCCheckbox(checkbox)
instance.indeterminate = indeterminate
if (context !== "list-item") {
let fieldStore = getContext("BBMD:field-element")
fieldStore.setInput(instance)
//TODO: Fix this connected to Formfield context issue
// let fieldStore = _bb.getContext("BBMD:field-element")
// fieldStore.setInput(instance)
}
}
})

View File

@ -3,13 +3,14 @@
import ClassBuilder from "../ClassBuilder.js"
import { fieldStore } from "./FormfieldStore.js"
import { MDCFormField } from "@material/form-field"
import { onMount, onDestroy, setContext } from "svelte"
import { onMount, onDestroy } from "svelte"
const cb = new ClassBuilder("form-field")
let store
const unsubscribe = fieldStore.subscribe(s => (store = s))
export let _bb
export let id = ""
export let label = ""
export let alignEnd = false
@ -23,7 +24,8 @@
onMount(() => {
if (!!formField) fieldStore.set(new MDCFormField(formField))
setContext("BBMD:field-element", fieldStore)
//TODO: Fix this, _bb is coming back undefined
// _bb.setContext("BBMD:field-element", fieldStore)
})
onDestroy(unsubscribe)

View File

@ -13,19 +13,40 @@
export let onSelect = selectedItems => {}
export let variant = "one-line"
//items: [{text: string | {primary: string, secondary: string}, value: any, selected: bool}...n]
export let items = []
export let singleSelection = false
export let variant = "two-line"
export let inputElement = null
let selectedItems = []
//TODO: Try managing selected list items with a store that is passed into context. This way can check within the component whether list item is selected to not selecteds instead of managing from internal state which is not feasible
function handleSelected(item) {
let idx = selectedItems.findIndex(i => i._id === item._id)
if (idx > -1) {
selectedItems.splice(idx, 1)
selectedItems = selectedItems
} else {
if (singleSelection) {
selectedItems = [item]
} else {
selectedItems = [...selectedItems, item]
}
}
}
//See todo above
_bb.setContext("BBMD:list:selectItem", handleSelected)
let role = "listbox"
onMount(() => {
_bb.setContext("BBMD:list:props", { inputElement, variant })
if (!!list) {
instance = new MDCList(list)
instance.singleSelection = singleSelection
instance.listElements.map(element => new MDCRipple(element))
if (!inputElement) {
instance.listElements.map(element => new MDCRipple(element))
}
}
let context = getContext("BBMD:list:context")
@ -39,28 +60,6 @@
}
})
function handleSelectedItem(item) {
if (!item.disabled) {
if (singleSelection || inputElement === "radiobutton") {
items.forEach(i => {
if (i.selected) i.selected = false
})
}
let idx = items.indexOf(item)
if (!!item.selected) {
items[idx].selected = !item.selected
} else {
items[idx].selected = true
}
onSelect(items.filter(item => item.selected))
}
}
$: useDoubleLine =
variant == "two-line" &&
items.every(i => typeof i.text == "object" && "primary" in i.text)
$: list && _bb.attachChildren(list)
$: modifiers = { variant }

View File

@ -1,17 +1,23 @@
<script>
import { onMount, getContext } from "svelte"
import { onMount } from "svelte"
import { Radiobutton } from "../Radiobutton"
import { Checkbox } from "../Checkbox"
import ClassBuilder from "../ClassBuilder.js"
import shortid from "shortid"
const cb = new ClassBuilder("list-item")
export let onClick = item => {}
let _id
let listProps = null
export let _bb
export let value = null
export let text = ""
export let secondaryText = ""
export let variant = "two-line"
export let inputElement = null
export let leadingIcon = ""
export let trailingIcon = ""
export let selected = false
@ -19,33 +25,51 @@
let role = "option"
function handleClick() {
if (!disabled) {
const selectItem = _bb.getContext("BBMD:list:selectItem")
selected = !selected
selectItem({
_id,
value,
text,
secondaryText,
selected,
disabled,
})
}
}
onMount(() => {
let context = getContext("BBMD:list:context")
_id = shortid.generate()
listProps = _bb.getContext("BBMD:list:props")
let context = _bb.getContext("BBMD:list:context")
if (context === "menu") {
role = "menuitem"
}
})
$: if (!!inputElement) {
setContext("BBMD:input:context", "list-item")
$: if (listProps && !!listProps.inputElement) {
_bb.setContext("BBMD:input:context", "list-item")
}
$: shouldSel = selected && !listProps
$: console.log("Should Select", selected)
$: modifiers = {
selected,
selected: selected && (!listProps || !listProps.inputElement),
disabled,
}
$: props = { modifiers }
$: listItemClass = cb.build({ props })
$: useTwoLine = variant === "two-line" && !!secondaryText
$: useTwoLine =
listProps && listProps.variant === "two-line" && !!secondaryText
</script>
<li
class={listItemClass}
role="option"
aria-selected={selected}
tabindex="0"
on:click={onClick}>
<li class={listItemClass} role="option" tabindex="0" on:click={handleClick}>
{#if leadingIcon}
<span class="mdc-list-item__graphic material-icons" aria-hidden="true">
{leadingIcon}
@ -58,11 +82,11 @@
{:else}{text}{/if}
</span>
{#if inputElement}
{#if inputElement === 'radiobutton'}
<Radiobutton checked={selected} {disabled} />
{:else if inputElement === 'checkbox'}
<Checkbox checked={selected} {disabled} />
{#if listProps}
{#if listProps.inputElement === 'radiobutton'}
<Radiobutton checked={selected} {disabled} {_bb} />
{:else if listProps.inputElement === 'checkbox'}
<Checkbox checked={selected} {disabled} {_bb} />
{/if}
{:else if trailingIcon}
<!-- TODO: Adapt label to accept class prop to handle this. Context is insufficient -->

View File

@ -1,10 +1,11 @@
<script>
import { onMount, onDestroy, getContext } from "svelte"
import { onMount, onDestroy } from "svelte"
import Formfield from "../Common/Formfield.svelte"
import ClassBuilder from "../ClassBuilder.js"
import { MDCRadio } from "@material/radio"
export let onClick = item => {}
export let _bb
export let id = ""
export let label = ""
@ -16,14 +17,15 @@
let instance = null
let radiobtn = null
let context = getContext("BBMD:input:context")
let context = _bb.getContext("BBMD:input:context")
onMount(() => {
if (!!radiobtn) {
instance = new MDCRadio(radiobtn)
if (context !== "list-item") {
let fieldStore = getContext("BBMD:field-element")
fieldStore.setInput(instance)
//TODO: Fix this connected to Formfield context issue, _bb not binding properly
// let fieldStore = _bb.getContext("BBMD:field-element")
// fieldStore.setInput(instance)
}
}
})

View File

@ -32,10 +32,6 @@
Button,
BodyBoundToStore,
Textfield,
Checkbox,
Checkboxgroup,
Radiobutton,
Radiobuttongroup,
Icon,
Datatable,
CustomersIndexTable,

View File

@ -117,12 +117,14 @@ export const props = {
CustomersIndexTable: indexDatatable(templateOptions)[0].props,
List: {
_component: "@budibase/materialdesign-components/List",
variant: "two-line",
inputElement: "radiobutton",
singleSelection: true,
onSelect: selected => console.log(selected),
_children: [
{
_component: "@budibase/materialdesign-components/ListItem",
_children: [],
variant: "two-line",
singleSelection: true,
text: "Curry",
secondaryText: "Chicken or Beef",
value: 0,
@ -131,8 +133,6 @@ export const props = {
{
_component: "@budibase/materialdesign-components/ListItem",
_children: [],
variant: "two-line",
singleSelection: true,
text: "Pastie",
secondaryText: "Bap with Mayo",
value: 1,
@ -141,15 +141,10 @@ export const props = {
{
_component: "@budibase/materialdesign-components/ListItem",
_children: [],
variant: "two-line",
singleSelection: true,
text: "Fish",
secondaryText: "Salmon or Cod",
value: 2,
},
],
variant: "two-line",
singleSelection: true,
onSelect: selected => console.log(selected),
]
},
}