如何通过单击一个来修改其他组件

时间:2019-05-25 21:43:27

标签: angular

我想单击类型为CardComponent的任何组件,然后为其他组件更改变量currentState。但是似乎currentState不能更改-使用this时只能为单击的元素更改。

let numInstances = 0;

@Component({
  selector: 'app-card',
  templateUrl: './card.component.html',
  styleUrls: ['./card.component.scss'],
  animations: [
    trigger('change', [
      state('show', style({
        opacity: 1
      })),
      state('hide', style({
        opacity: 0
      })),
      transition('show=>hide', animate('150ms')),
      transition('hide=>show', animate('150ms'))
    ])
  ]
})
export class CardComponent {

  currentState = 'show';

  private instanceId: number;

  constructor() {
    this.instanceId = numInstances++;
  }

  get id() {
    return 'card_' + this.instanceId;
  }

  public toggle(): void {
    const items = document.getElementsByClassName('card-container'); // other items
    for (const item of items as any) {
      if (item.id !== this.id) {
        item.currentState = 'hide'; // current state is not changing
      } else {
        this.currentState = 'show'; // when using this, state is changing
      }
    }
  }
}

如何更改其他项目的currentState

1 个答案:

答案 0 :(得分:1)

在大多数情况下,

在角度上,尝试操纵DOM和通过vanillajs访问是个坏主意。

我建议您使用Angular Core团队建议的设计来修改代码。

容器和UI组件

这意味着您具有代表用户界面的组件。该组件仅使用输入/输出与您的应用程序其余部分进行交互。这将帮助您使UI通用且易于更改。

它们可能如下所示:

@Component({
  selector: 'hello',
  template: `<h1 (click)="onClickHandler()">{{ isActive && 'Hello' || 'Bye' }} {{name}}!</h1>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() name: string;
  @Input() isActive: boolean = false;
  @Output() onClick: EventEmitter<string> = new EventEmitter();
  onClickHandler() {
    this.onClick.emit(this.name);
  }
}

这里有可以接收的基本UI组件:

  • 名称(作为ID)
  • 处于活动状态。

然后发射:

  • 单击时。

然后您将拥有Container组件,该组件的作用是在数据存储,业务逻辑,api请求...和UI之间架起桥梁。

如下所示:

export class AppComponent  {
  constructor(public storeService: StoreService) {}

  isActive(name: string): Observable<boolean> {
    return this.storeService.isActive(name);
  }

  setCurrent(name: string) {
    this.storeService.setCurrent(name);
  }
}

然后,大多数时候您都在服务中拥有商店和业务逻辑

@Injectable()
export class StoreService {
  private currentActive$ = new BehaviorSubject('Bob');

  isActive(name: string): Observable<boolean> {
    return this.currentActive$.pipe(map((current) => current === name));
  }

  setCurrent(name: string) {
    this.currentActive$.next(name);
  }
}

这里有一个可观察的currentActive$,它将跟踪您的拨动开关的所有变化。

您可以通过调用setCurrent方法来更新当前活动对象。

现在,您的UI想要知道他是否为当前活动对象。为此,您可以使用isActive(name: string): Observable<boolean>

它只是获取全局活动流,并将其映射为具有truefalse的流

Online demo