Skip to content

Instantly share code, notes, and snippets.

@zzarcon
Last active January 4, 2017 22:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zzarcon/cad6e94c103f0f6912e2d269647c38ce to your computer and use it in GitHub Desktop.
Save zzarcon/cad6e94c103f0f6912e2d269647c38ce to your computer and use it in GitHub Desktop.
Component: behavior + events
/** @jsx h */
import 'skatejs-web-components';
import { Component, h } from 'skatejs';
import styles from './styles';
class SKTags extends Component {
static props = {
delimiter: prop.string({attribute: true, default: ' '}),
tags: prop.array({attribute: true}),
}
renderCallback() {
const tagElements = this.tags.map(t => <span class="tag">{t}</span>);
return <div>
<style>{styles}</style>
<div class='wrapper' onclick={this.onWrapperClick}>
<span class='tags'>{tagElements}</span>
<input type="text" oninput={this.onInput} onkeydown={this.onKeydown} autofocus="true" class= 'input'/>
</div>
</div>
}
onWrapperClick = e => {
this.focusInput();
}
focusInput() {
this.shadowRoot.querySelector('.input').focus();
}
onKeydown = e => {
const value = e.target.value;
const isDel = e.keyCode === deleteCode;
if (isDel && value.length <= 0) {
this.removeTag();
}
}
onInput = e => {
const lastChar = e.target.value.substr(-1);
const value = e.target.value.slice(0, -1).trim();
const isDelimiter = lastChar === this.delimiter;
if (value && isDelimiter) {
this.addTag(value);
e.target.value = '';
}
this.adjustInputSize(e.target.value.length);
}
adjustInputSize(textLength) {
const input = this.shadowRoot.querySelector('.input');
const width = (textLength * 13) + 6;
input.style.width = `${width}px`;
}
addTag(value) {
this.tags = this.tags.concat(value);
}
}
customElements.define('sk-tags', SKTags);
@treshugart
Copy link

I would make use of the built-in props where possible. For delimiter you can use prop.string({ attribute: true, default: ' ' }). For tags you can use prop.array({ attribute: true }). However, that assumes a JSON array. If you don't want that, then your custom prop is fine, but using prop.array() would simplify the example for the readers.

@treshugart
Copy link

treshugart commented Jan 2, 2017

You can clean up the code if you're willing to use some ES2016 features such as property initialisers. For example, you can simplify props and all your event handlers:

class SKTags extends Component {
  // So you don't have to do a getter.
  static props = {}

  // Auto-binds the method to `this` so it can be passed off
  // as `oninput={this.onInput}`.
  onInput = e => {
    const lastChar = this.value.substr(-1);
    const value = this.value.slice(0, -1).trim();
    const isDelimiter = lastChar === component.delimiter;

    if (value && isDelimiter) {
      component.addTag(value);
      this.value = '';
    }

    component.adjustInputSize(this.value.length);
  }
}

@zzarcon
Copy link
Author

zzarcon commented Jan 3, 2017

@treshugart your suggestions make a lot of sense, already applied the changes, it looks easier to read now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment