14

What I'm using

  • Angular

What I'm trying to do

  • I have a list. When I hit a button, I want to append some custom attributes to a certain HTML element

What I have

  • My HTML List

  • A button hooked up to a click event

What I'm not sure how to do

  • When I click the button the follow attributes are added to my 'container' div:

[phantomOp]="myItems" [myOper]="oper"

HTML

<div class="container">
  <ul>
    <li> Albums </li>
    <li> Dates </li>
    </ul>
</div>

<button (click)="addContainerAttributes"> Add Container Attributes </button>

What I would like the HTML to look like after a button click

<div class="container" [phantomOp]="myItems" [myOper]="oper">
  <ul>
    <li> Albums </li>
    <li> Dates </li>
  </ul>
</div>

TS

addContainerAttributes(){
  // Not entirely sure what to put here
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Que
  • 957
  • 2
  • 14
  • 35
  • Could you set the attributes in the template, and change the values of `myItems` and `oper` when you click the button? That would appear more conventional to me. – ConnorsFan Oct 26 '17 at 15:29
  • That was my first plan. However, I'm using a plug in. When I include those attributes with empty values, the plugins functionality still works! lol. That's why I'm trying to add them on a button click. Thanks for the response ConnorsFan :) – Que Oct 26 '17 at 15:32
  • Did you try to set these attributes to `null` or to `undefined`, instead of giving them an empty value? – ConnorsFan Oct 26 '17 at 16:09

2 Answers2

17

Adding Angular specific markup added dynamically at runtime will just be ignored by Angular. Bindings like [phantomOp]="myItems" [myOper]="oper" are processed by Angular only when a component is compiled. Normally (with AoT) this is before you deploy your application.

How can I use/create dynamic template to compile dynamic Component with Angular 2.0? explains how to compile a component at runtime.

You can just introduce a field in your component

isClicked:boolean = false;

add this to your element statically

[phantomOp]="isClicked ? myItems : null" [myOper]="isClicked ? oper : null"

and in the click handler

(click)="isClicked=true"
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks Gunter. Empty values such as [phantomOp]="" [myOper]="" still make my plugin work, just without the additional options that would be passing through with each of those. Based on what you've said, it doesn't look like it's possible to do what I want to achieve. But this is a good answer non the less and was close to what I tried originally. Thanks for your time anyway :) – Que Oct 26 '17 at 15:37
  • Binding to null and not adding the binding at all should be pretty much the same. – Günter Zöchbauer Oct 26 '17 at 15:41
4

I ran into a similar situation recently. I wanted to dynamically add and remove the capture attribute on a FileInput. Now just the presence of the capture attribute and the File Input will fall to capture mode, so having the value as null or '' did not work for me.

This is how I finally got it to work. I used @ViewChild and ElementRef. In your case it would be something like:

<div #yourContainer class="container">
  <ul>
    <li> Albums </li>
    <li> Dates </li>
    </ul>
</div>

<button (click)="addContainerAttributes"> Add Container Attributes </button>

Then in the TS

import { Component, ElementRef } from '@angular/core';

@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
  styleUrls: ['./your-component.component.css']
})
export class YourComponent {
@ViewChild('yourContainer', {static:true}) yourContainer: ElementRef;

....

  addContainerAttributes(){
    // Not entirely sure what to put here
    this.yourContainer.nativeElement.setAttribute('phantomOp', myItems);
    this.yourContainer.nativeElement.setAttribute('myOper', oper);
  }

  // if you wish to completely remove the attribute dynamically
  removeContainerAttributes(){
    this.yourContainer.nativeElement.removeAttribute('phantomOp');
    this.yourContainer.nativeElement.removeAttribute('myOper');
  }
}

Chif
  • 830
  • 1
  • 7
  • 20