Переключение всех компонентов stencil.js одного и того же вида при нажатии - PullRequest
0 голосов
/ 07 ноября 2019

Я создаю панель инструментов, которая будет использоваться для редактирования текста.

Каждый элемент на панели инструментов создается с таким кодом:

import {Component, h, Prop, Event, EventEmitter} from '@stencil/core';

@Component({
  tag: 'spa-toolbar-item',
  styleUrl: 'spa-toolbar-item.scss',
})

export class spaToolbarItem {
  @Prop({reflectToAttr: true, mutable: true}) toggle: boolean = false;
  @Prop({reflectToAttr: true}) type: string;
  @Event() onToggle: EventEmitter;

  toggleComponent(): void {
    this.toggle = !this.toggle;
    this.onToggle.emit({visible: this.toggle});
  }

  render() {
    return [
      <button onClick={() => this.toggleComponent()}>
        <slot/>
      </button>,
      <div class={this.toggle ? 'is-active' : null}>
        {this.type == 'font'
          ? <div class={this.type}>
            <span class="arial">Arial</span>
            <span class="georgia">Georgia</span>
            <span class="palatino">Palatino</span>
            <span class="tahoma">Tahoma</span>
            <span class="times">Times New Roman</span>
            <span class="helvetica">Helvetica</span>
            <span class="courier">Courier New</span>
            <span class="lucida">Lucida Sans Typewriter</span>
            <span class="verdana">Verdana</span>
          </div>
          : null}
      </div>
    ]
  }
}

Однако это работает, как и ожидалосьЯ хочу, чтобы все другие раскрывающиеся меню закрывались при нажатии на один элемент, поэтому в основном «this.toggle» необходимо применять для всех неактивных раскрывающихся списков. Как мне это сделать?

Ответы [ 3 ]

0 голосов
/ 08 ноября 2019

Таким образом, идея заключается в том, чтобы применить addEventListener к вашему документу, а также к самому компоненту (хост - выпадающий список). Для этого вы можете использовать жизненный цикл, например componentdidload.

import {Component, h, Prop, Event, EventEmitter} from '@stencil/core';

@Component({
  tag: 'spa-toolbar-item',
  styleUrl: 'spa-toolbar-item.scss',
})

export class spaToolbarItem {
  @Prop({reflectToAttr: true, mutable: true}) toggle: boolean = false;
  @Prop({reflectToAttr: true}) type: string;
  @Event() onToggle: EventEmitter;

private hostElement;
private buttonElement;
  closeDropdown(){
    this.toggle = false;
  }
  toggleComponent(): void {
    this.toggle = !this.toggle;
    this.onToggle.emit({visible: this.toggle});
  }

render() {
 return 
 <Host ref={(el) => this.hostElement = el}>
   //everything you had before in the return value
 </Host>
}

 componentDidLoad(){
  document.addEventListener("click", ()=>{this.clickManager("document");}, true)
  this.hostElement.addEventListener("click", ()=>{this.clickManager("dropdown");}, true)
 }

 private clickManager(identifier){
   if(identifier == "dropdown"){
     //the clicked dropdown -> active dropdown
     this.toggleComponent();
     return;
   }
   //all non active Dropdowns
   this.closeDropdown();
 }

}

. Как вы видите, у нас есть два события, которые вызывают clickManager. Первый - это документ, а второй - раскрывающийся список, по которому вы щелкнули. Конечно, вы должны удалить событие onclick на кнопке, но этот код не работает должным образом. Теперь вы можете решить, что произойдет, если вы щелкнете по раскрывающемуся списку и что произойдет со всеми неактивными раскрывающимися списками.

Это базовая концепция, которую вы можете адаптировать и изменить при необходимости.

0 голосов
/ 08 ноября 2019

Спасибо, Кристиан, в итоге я воспользовался этим решением.

import {Component, h, Prop, Host, Element} from '@stencil/core';

@Component({
  tag: 'spa-toolbar-item',
  styleUrl: 'spa-toolbar-item.scss',
})

export class spaToolbarItem {
  @Prop({reflectToAttr: true, mutable: true}) isOpen: string = 'false';
  @Prop({reflectToAttr: true}) type: string;
  @Element() el: HTMLElement;

  openDropdown() {
    function closeDropdown() {
      let dropdowns = document.querySelectorAll('spa-toolbar-item[is-open]');
      dropdowns.forEach(item => {
        item.setAttribute('is-open', 'false')
      });
    }

    if (this.el.getAttribute('is-open') == 'true') {
      closeDropdown();
      return
    }

    if (this.el.getAttribute('is-open') == 'false') {
      closeDropdown();
      this.el.setAttribute('is-open', 'true')
    }
  }

  render() {
    return (
      <Host>
        <button onClick={this.openDropdown.bind(this)}>
          <slot/>
        </button>
        <div class={this.type}>
          {this.type == 'font'
            ? <div>
              <span class="arial">Arial</span>
              <span class="georgia">Georgia</span>
              <span class="palatino">Palatino</span>
              <span class="tahoma">Tahoma</span>
              <span class="times">Times New Roman</span>
              <span class="helvetica">Helvetica</span>
              <span class="courier">Courier New</span>
              <span class="lucida">Lucida Sans Typewriter</span>
              <span class="verdana">Verdana</span>
            </div>
            : null}
        </div>
      </Host>
    )
  }
}
0 голосов
/ 07 ноября 2019

то, что вы можете сделать с чистым javascript, состоит в том, чтобы перебрать все элементы с активным классом и установить свойства переключения каждого из них на 0 (или как вы это делаете)

пример:

new Array(document.getElementsByClassName('is-active')).forEach(function(e){/*Set toggle property to 0*/});

что это такое, найти все элементы с is-active, выполнить итерации по ним и установить функцию, в этой функции параметр e равен текущему элементуВы можете установить свою собственность там.

...