Skip to content

Commit

Permalink
feat(select): add required property
Browse files Browse the repository at this point in the history
  • Loading branch information
jgroth authored and adrianschmidt committed Sep 10, 2019
1 parent e280e3b commit 49bdc0d
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 8 deletions.
23 changes: 21 additions & 2 deletions src/components/select/select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ $mdc-select-bottom-line-hover-color: $lime-text-field-bottom-line-color;
}
}

.mdc-menu-surface--anchor {
.limel-select {

&,
.limel-select-trigger,
Expand All @@ -63,7 +63,7 @@ $mdc-select-bottom-line-hover-color: $lime-text-field-bottom-line-color;
.limel-select-trigger {
display: inline-flex;
cursor: pointer;
orting Option,

&:focus {
outline: none;

Expand Down Expand Up @@ -107,6 +107,25 @@ $mdc-select-bottom-line-hover-color: $lime-text-field-bottom-line-color;
}
}

&.limel-select--required {
.mdc-floating-label::after {
content: "*";
}
}

&.limel-select--invalid {
.limel-select-trigger {
.mdc-floating-label {
color: $mdc-theme-error;
}
.mdc-line-ripple {
background-color: $mdc-theme-error;
transform: scaleX(1);
opacity: 1;
}
}
}

.mdc-menu-surface {
left: 0;
top: pxToRem(56);
Expand Down
11 changes: 11 additions & 0 deletions src/components/select/select.template.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Option } from './option.types';

interface SelectTemplateProps {
disabled?: boolean;
required?: boolean;
options: Option[];
value: Option | Option[];
label?: string;
Expand Down Expand Up @@ -43,6 +44,8 @@ export const NativeSelectTemplate: FunctionalComponent<
{getSelectedText(props.value)}
</div>
<select
required={props.required}
aria-required={props.required}
onChange={props.onChange}
class="mdc-select__native-control"
disabled={props.disabled}
Expand Down Expand Up @@ -79,6 +82,7 @@ interface MenuSelectTemplateProps extends SelectTemplateProps {
isOpen: boolean;
open: () => void;
close: () => void;
checkValid: boolean;
}

export const MenuSelectTemplate: FunctionalComponent<
Expand All @@ -92,12 +96,19 @@ export const MenuSelectTemplate: FunctionalComponent<
hasValue = !!(props.value as Option).value;
}

let isValid = true;
if (props.checkValid && props.required && !hasValue) {
isValid = false;
}

return (
<div
class={`
limel-select
mdc-menu-surface--anchor
${props.disabled ? 'mdc-select--disabled' : ''}
${props.required ? 'limel-select--required' : ''}
${!isValid ? 'limel-select--invalid' : ''}
`}
>
<div
Expand Down
28 changes: 25 additions & 3 deletions src/components/select/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
EventEmitter,
Prop,
State,
Watch,
} from '@stencil/core';
import { isArray } from 'lodash-es';
import { Option } from '../../interface';
Expand Down Expand Up @@ -36,6 +37,12 @@ export class Select {
@Prop({ reflectToAttr: true })
public disabled = false;

/**
* True if the control requires a value
*/
@Prop({ reflectToAttr: true })
public required = false;

/**
* Text to display next to the select
*/
Expand Down Expand Up @@ -63,6 +70,8 @@ export class Select {
@State()
private menuOpen: boolean = false;

private checkValid: boolean = false;

/**
* Emitted when the value is changed
*/
Expand Down Expand Up @@ -101,9 +110,7 @@ export class Select {
public componentDidLoad() {
let element: HTMLElement;
if (!this.isMobileDevice) {
element = this.host.shadowRoot.querySelector(
'.mdc-floating-label'
);
element = this.host.shadowRoot.querySelector('.mdc-floating-label');
this.mdcFloatingLabel = new MDCFloatingLabel(element);

element = this.host.shadowRoot.querySelector('.mdc-line-ripple');
Expand Down Expand Up @@ -151,6 +158,7 @@ export class Select {
return (
<MenuSelectTemplate
disabled={this.disabled}
required={this.required}
label={this.label}
value={this.value}
options={this.options}
Expand All @@ -159,13 +167,15 @@ export class Select {
isOpen={this.menuOpen}
open={this.openMenu}
close={this.closeMenu}
checkValid={this.checkValid}
/>
);
}

return (
<NativeSelectTemplate
disabled={this.disabled}
required={this.required}
label={this.label}
value={this.value}
options={this.options}
Expand All @@ -175,6 +185,18 @@ export class Select {
);
}

@Watch('menuOpen')
protected watchOpen(newValue: boolean, oldValue: boolean) {
if (this.checkValid) {
return;
}

// Menu was closed for the first time
if (!newValue && oldValue) {
this.checkValid = true;
}
}

private handleMenuChange(
event: CustomEvent<Array<ListItem<Option>> | ListItem<Option>>
) {
Expand Down
1 change: 1 addition & 0 deletions src/examples/select/select-initially-empty-required.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class SelectExample {
value={this.value}
options={this.options}
onChange={this.onChange}
required={true}
/>
<p>Value: {JSON.stringify(this.value)}</p>
</section>
Expand Down
21 changes: 18 additions & 3 deletions src/examples/select/select-multiple.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export class SelectMultipleExample {
@State()
public disabled = false;

@State()
public required = false;

private options: Option[] = [
{ text: 'Luke Skywalker', value: 'luke' },
{ text: 'Han Solo', value: 'han' },
Expand All @@ -22,6 +25,7 @@ export class SelectMultipleExample {
constructor() {
this.onChange = this.onChange.bind(this);
this.toggleEnabled = this.toggleEnabled.bind(this);
this.toggleRequired = this.toggleRequired.bind(this);
}

public render() {
Expand All @@ -32,14 +36,21 @@ export class SelectMultipleExample {
value={this.value}
options={this.options}
disabled={this.disabled}
required={this.required}
onChange={this.onChange}
multiple={true}
/>
<p>
<limel-flex-container justify="end">
<limel-button
onClick={this.toggleEnabled}
label={this.disabled ? 'Enable' : 'Disable'}
<limel-checkbox
label="Disabled"
onChange={this.toggleEnabled}
checked={this.disabled}
/>
<limel-checkbox
label="Required"
onChange={this.toggleRequired}
checked={this.required}
/>
</limel-flex-container>
</p>
Expand All @@ -55,4 +66,8 @@ export class SelectMultipleExample {
private toggleEnabled() {
this.disabled = !this.disabled;
}

private toggleRequired() {
this.required = !this.required;
}
}

0 comments on commit 49bdc0d

Please sign in to comment.