From f03d407590fbecf9c11258f21fa41dd02d9f28ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Jurmanovi=C4=87?= Date: Thu, 10 Jun 2021 22:31:12 +0200 Subject: [PATCH] custom dropdown element --- src/common/core/BaseElement/BaseElement.ts | 9 +- .../app-dropdown/AppDropdownElement.ts | 160 +++++++++++++----- src/components/app-form/AppFormElement.ts | 12 +- src/components/app-link/AppLinkElement.ts | 2 +- .../app-pagination/AppPaginationElement.ts | 4 +- .../input-field/InputFieldElement.ts | 6 +- src/components/menu-item/MenuItemElement.ts | 2 +- src/pages/home-page/HomePageElement.ts | 2 +- src/styles/app-dropdown/app-dropdown.scss | 107 ++++++++++++ src/styles/app-dropdown/index.scss | 1 + src/styles/main.scss | 1 + 11 files changed, 251 insertions(+), 55 deletions(-) create mode 100644 src/styles/app-dropdown/app-dropdown.scss create mode 100644 src/styles/app-dropdown/index.scss diff --git a/src/common/core/BaseElement/BaseElement.ts b/src/common/core/BaseElement/BaseElement.ts index 59e1c64..1a314e9 100644 --- a/src/common/core/BaseElement/BaseElement.ts +++ b/src/common/core/BaseElement/BaseElement.ts @@ -48,10 +48,10 @@ class BaseElement extends HTMLElement { return this.appMain?.isAuth(); } - public bindEvents = (): void => { - const _elems = this.querySelectorAll("[data-action]"); + public bindEvents = (attrName): void => { + const _elems = this.querySelectorAll(`[${attrName}]`); _elems?.forEach((el) => { - for (const action of (el.getAttribute("data-action") || "") + for (const action of (el.getAttribute(attrName) || "") .trim() .split(/\s+/)) { const eventSep = action.lastIndexOf(":"); @@ -88,7 +88,8 @@ class BaseElement extends HTMLElement { update = (): void => { render(this.render(), this); - this.bindEvents(); + this.bindEvents("data-action"); + this.bindEvents("app-action"); this.updateCallback(); }; diff --git a/src/components/app-dropdown/AppDropdownElement.ts b/src/components/app-dropdown/AppDropdownElement.ts index cff3a56..495907a 100644 --- a/src/components/app-dropdown/AppDropdownElement.ts +++ b/src/components/app-dropdown/AppDropdownElement.ts @@ -1,7 +1,6 @@ import { attr, controller, target } from "@github/catalyst"; import { findMethod, firstUpper } from "core/utils"; -import { html, TemplateResult } from "@github/jtml"; -import { RouterService } from "core/services"; +import { html } from "@github/jtml"; import randomId from "core/utils/random-id"; import validator from "validator"; import { validatorErrors } from "core/constants"; @@ -14,12 +13,20 @@ class AppDropdownElement extends BaseComponentElement { @attr rules: string; @target main: HTMLElement; @target inp: HTMLElement; - @attr displaykey: string; - @attr valuekey: string; + @attr displaykey: string = "name"; + @attr valuekey: string = "id"; @attr fetch: string; fetchFunc: any; - error: string; + + error: boolean; + errorMessage: string; + + searchPhrase: string; + randId: string; + value: string; + + @attr isOpen: boolean = false; items: Array; totalItems: number; @@ -51,32 +58,20 @@ class AppDropdownElement extends BaseComponentElement { items = []; } this.items = items; - this.renderOptions(items); - this.renderOptions(items); + this.update(); } }; - private renderOptions = (items) => { - const displayKey = this.displaykey || "name"; - const valueKey = this.valuekey || "id"; - - const options = items?.map((item) => { - const val = { name: item[displayKey], value: item[valueKey] }; - if ( - this.optionValues.some((value) => { - if (value.name == val.name && value.value == val.value) { - return true; - } - return false; - }) - ) - return; - const _option = document.createElement("option"); - _option.setAttribute("value", val.value); - _option.innerText = val.name; - this.inp?.appendChild(_option); + get selectedItem() { + const { value, valuekey, items } = this; + const item = items?.find((item) => { + return value == item[valuekey]; }); - }; + + console.log(item, value, valuekey); + + return item; + } get optionValues() { let values = []; @@ -88,10 +83,6 @@ class AppDropdownElement extends BaseComponentElement { return values; } - onChange = () => { - this.renderOptions(this.items); - }; - public elementConnected = (): void => { this.randId = `${name}${randomId()}`; this.fetchFunc = findMethod(this.fetch, this.appMain); @@ -104,6 +95,10 @@ class AppDropdownElement extends BaseComponentElement { this.getItems(options); }; + attributeChangedCallback(): void { + this.update(); + } + get valid(): boolean { return !!this.error; } @@ -144,13 +139,102 @@ class AppDropdownElement extends BaseComponentElement { return _return; } - render = (): TemplateResult => { - return html`
- -
`; + openDropdown = () => { + this.isOpen = true; + }; + + stopPropagation = (e) => { + e.stopPropagation(); + }; + + toggleDropdown = () => { + const isOpen = this.isOpen; + this.isOpen = !isOpen; + }; + + itemSelected = (e) => { + const value = (e.target as HTMLSpanElement).getAttribute("data-value"); + this.value = value; + this.isOpen = false; + }; + + get _value() { + return this.value; + } + + render = () => { + const { + label, + error, + errorMessage, + isOpen, + searchPhrase, + items, + selectedItem, + displaykey, + valuekey, + } = this; + + console.log(isOpen); + + const renderItem = (item) => { + return html` `; + }; + + const renderItems = (_items) => { + return _items.map((item) => renderItem(item)); + }; + + return html` +
+ +
+ `; }; } diff --git a/src/components/app-form/AppFormElement.ts b/src/components/app-form/AppFormElement.ts index 51d56bd..0f75060 100644 --- a/src/components/app-form/AppFormElement.ts +++ b/src/components/app-form/AppFormElement.ts @@ -65,13 +65,11 @@ class AppFormElement extends BaseComponentElement { get values(): any { const formObject: any = {}; this.inputField.forEach((input: InputFieldElement) => { - const inputType = input.inp; - formObject[input.name] = (inputType as HTMLInputElement).value; + formObject[input.name] = input._value; }); this.appDropdown?.forEach((input: AppDropdownElement) => { - if (input.required && (input.inp as HTMLSelectElement).value) { - const inputType = input.inp; - formObject[input.name] = (inputType as HTMLSelectElement).value; + if (input.required && input.value) { + formObject[input.name] = input._value; } }); return formObject; @@ -114,7 +112,7 @@ class AppFormElement extends BaseComponentElement { if (hasCancel) { return html``; @@ -123,7 +121,7 @@ class AppFormElement extends BaseComponentElement { }; return html`
diff --git a/src/components/app-link/AppLinkElement.ts b/src/components/app-link/AppLinkElement.ts index af08f85..f7bcd68 100644 --- a/src/components/app-link/AppLinkElement.ts +++ b/src/components/app-link/AppLinkElement.ts @@ -61,7 +61,7 @@ class AppLinkElement extends BaseComponentElement { : html`${this.title} Prev @@ -132,7 +132,7 @@ class AppPaginationElement extends BaseComponentElement { pageRange ? "disabled" : ""}" - data-action="click:app-pagination#pageNext" + app-action="click:app-pagination#pageNext" > Next diff --git a/src/components/input-field/InputFieldElement.ts b/src/components/input-field/InputFieldElement.ts index 75b361b..64b87c5 100644 --- a/src/components/input-field/InputFieldElement.ts +++ b/src/components/input-field/InputFieldElement.ts @@ -38,6 +38,10 @@ class InputFieldElement extends BaseComponentElement { return this.rules.includes("required"); } + get _value() { + return (this.inp as HTMLInputElement)?.value; + } + validate = (): boolean => { let _return = true; const rules = this.rules?.split("|").filter((a) => a); @@ -104,7 +108,7 @@ class InputFieldElement extends BaseComponentElement { return html` + ` diff --git a/src/pages/home-page/HomePageElement.ts b/src/pages/home-page/HomePageElement.ts index a31080e..297a1a0 100644 --- a/src/pages/home-page/HomePageElement.ts +++ b/src/pages/home-page/HomePageElement.ts @@ -53,7 +53,7 @@ class HomePageElement extends BasePageElement { render = (): TemplateResult => { return html` - +