2

I'm creating a component that changes an index based on the value selected from a dropdown. The dropdown itself is a stylised one rather than a native element and so updates a hidden input field. That field is in the template and has a binding with the variable in the component.

Here is the component and template:

import { Component, ElementRef, Input, OnInit } from '@angular/core';
import { Spell } from '../../models/spell';

/**
 * This class represents a Spell component
 */
@Component({
  moduleId: module.id,
  selector: 'ui-spell',
  templateUrl: 'spell.component.html',
  styleUrls: ['spell.component.css']
})
export class SpellComponent implements OnInit {
  @Input() spell: Spell;

  level: number;

  constructor(private el: ElementRef) {
    this.level = 1;
  }

  ngOnInit() {
  }

  update() {
    console.log(this.level);
  }
}

<div class="ui dropdown button">
  <input name="level" type="hidden" [(ngModel)]="level">
  <div class="text">Rank 1</div>
  <i class="dropdown icon"></i>
  <div class="menu">
    <div class="item" data-value="1">Rank 1</div>
    <div class="item" data-value="2">Rank 2</div>
    <div class="item" data-value="3">Rank 3</div>
    <div class="item" data-value="4">Rank 4</div>
    <div class="item" data-value="5">Rank 5</div>
  </div>
</div>
<button (click)="update()">Update</button>

The value of the input successfully changes but if I click on the Update button, the level still outputs as '1'. If I change the starting value in the component and inspect the input, the value has changed to match. There's no errors anywhere to explain why the value is not returned to the component. I have no idea where to look next.

3
  • 1
    You aren't binding the dropdown to anything, so I'm not sure why you'd expect the level input to actually update to anything else. Commented Apr 18, 2017 at 16:14
  • For ngModel to take up the change, you need to ensure the change event is fired from the <input type="hidden"> for ngModel to take up the change. @Input() is redundant here because it's only relevant when you pass data to SpellComponent from the outside - like <ui-spell [spell]="1"> Commented Apr 18, 2017 at 16:15
  • I knew someone would get confused by the @Input() spell... It's not used in the dropdown part of the template, it's an object I'm passing in that the dropdown is going to select an index from (there's 1 line missing from the template that's just "{{ spell.mana[level] }}" as a test at the moment). And in regards to David's comment, I don't understand what you mean. the input field is bound to "level". Commented Apr 18, 2017 at 16:23

2 Answers 2

1

I'd use something like

<div class="item" (click)="level = 1" data-value="1">Rank 1</div>
<div class="item" (click)="level = 2" data-value="2">Rank 2</div>
<div class="item" (click)="level = 3" data-value="3">Rank 3</div>
<div class="item" (click)="level = 4" data-value="4">Rank 4</div>
<div class="item" (click)="level = 5" data-value="5">Rank 5</div>
Sign up to request clarification or add additional context in comments.

3 Comments

I may have to go that way but I'm worried it will stop the existing click events.
As long as you don't return false from (click)="..." it shouldn't affect other click handlers.
Thank you. This works. I was overcomplicating things considering I didn't need to maintain the state of the selection.
1

You can only bind to objects in Angular as far as i know. Create an object with level as property and it should work. Vanilla JS syntax here:

var data = {level: 1};
//...

update() {
    console.log(this.level);
}

Bind to data.level:

<input name="level" type="hidden" [(ngModel)]="data.level">

2 Comments

I think you can, otherwise it wouldn't be passing the level value to the input as it currently does, it's just not sending any update back the other way.
I remember that behavior from an Angular 1.x project but may be this is outdated. Variables are passed by value, object by reference in JS, that could explain the one-way binding instead of two-way.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.