0

I'm trying to use data received through an @Output to trigger if statements inside my component. For testing purposes I have this in the template

{{selectedAnswer | json}}

When I select answers in the child component this binding works in the parent component showing the data is reaching the variable selectedAnswer. Yet when I do console.log(this.selectedAnswer) nothing logs.

I've also been trying to get it to update to a variable to run the if conditions. When the page first loads it picks up the value of the first radio button when I don't have any selected by default. When I click through them the value updates in the test binding but nothing changes in the console.logs.

This is what's going on in the parent component.

//data coming in from @Output in child component
public selectedI(selected){ this.selectedAnswer = selected };

//the variable I'm passing it into for use.
selectedAnswer: any;

ngOnChanges() {

    //my way so far of attempting to get the value I want when a selection is made.
    var trigger = this.selectedAnswer? this.selectedAnswer.value1: '';



    console.log(this.selectedAnswer);
}

Template

<multiple-choice-radio *ngIf="expbTrigger"
    [question]  = "question01"
    (selectedO) = "selectedI($event)"
></multiple-choice-radio>

The only thing different in calling it here vs. calling it in the binding is the binding has a |json pipe added to it. Am I suppose to be doing the same thing somehow inside the expression? The way the data is being collected in the child component is like this

@Output() selectedO: EventEmitter<any> = new EventEmitter();

//variable for storing values from (click) event
selected = {value1: '', value2: ''};

//(click) event that gets values from template and passes them into "selected"
getSelected(ans) {
    this.selected = { value1: ans.id, value2: ans.answer };
}

//(click) event that sends @Output data to parent component.
public sendAnswer = (): void => {
     this.selectedO.emit(this.selected);
 }

Template

<input type="radio"
    [attr.name]  = "quesForm.value.name"
    [attr.id]    = "ans.id"
    [attr.value] = "ans.answer"
    (click)      = "getSelected(ans)"
    (click)      = "sendAnswer()"
    hidden
/>

I've personally been feeling the way I'm doing all this is a bit bulky so if you know of a cleaner way to do this please share. Other than that, how can I get this to log in the console as well as be accessible for further use in triggering logic upon updates?

4
  • 1
    update the post with your html markups Commented Feb 18, 2017 at 21:35
  • just updated it Commented Feb 18, 2017 at 21:45
  • why do you have two click handlers in your HTML? Commented Feb 18, 2017 at 22:05
  • like I said, I felt this was a little bulky, but it's the only way so far that I've come up with where the data flows the way I want to use it. Commented Feb 18, 2017 at 22:13

2 Answers 2

1

Try using SimpleChanges in angular2

import { SimpleChanges } from '@angular/core'
ngOnChanges(changes: SimpleChanges) {
    console.log(changes);// to log if any changes are detected.

}

Possible mistake

  1. Your this.selected is not a input property

Note: Angular calls its ngOnChanges method whenever it detects changes to input properties of the component (or directive).

Alternatively, if you are assigning the variable to some DOM element using [ngModel] you can trigger (ngModelChange) event manually.

<input type="text" [ngModel]="selected" (ngModelChange)="onSelectedChange($event)" />

You need to handle the method as

onSelectedChange(val){
     .....
}

Best Practice

Among all other alternatives when you are handling an @output property you are using a method in your component and you can place all your logic into that method itself instead of using the above.

Check out ngDoCheck and ChangeDetectionStrategy to detect all changes you can use this answer of mine. But ngDoCheck() checks for mouse and keyboard events which causes great overhead.

Sign up to request clarification or add additional context in comments.

10 Comments

is there anything else I'm suppose to import? It's throwing an error saying it can't find SimpleChanges
I'm passing the this.selected into the event, it was the only way I could get the data to even show in the parent component.
and SimpleChanges isn't detecting anything from selectedAnswer
I've been reading the answer you linked it to and checking more into the ngDoCheck, thanks for the info.
mark this answer and upvote both too as it helped you. :)
|
0

If you want to render a radio button list, and handle a click event when the user clicks an answer, I would set it up this way:

Interfaces

interface Choice {
    id:number,
    name:string;
}

interface Question {
    text: string;
    choices: Choice[];
}

Child Component

@Component({
    moduleId: module.id,
    selector: 'child',
    template: `
        <div>
            {{ question.text }}
        </div>

        <div *ngFor="let option of question.choices">
            <input type="radio" (click)="selectOption(option)" name="options" [value]="option.id">{{option.name}}<br>
       </div>

    `
})
export class ChildComponent {
    @Input() question: Question;
    @Output() selected: EventEmitter<Choice>;
    constructor() {
        this.selected = new EventEmitter<Choice>();
    }

    selectOption(choice:Choice) {
        this.selected.next(choice);
    }
}

Parent Component

@Component({
    moduleId: module.id,
    selector: 'parent',
    template: `
        Options: 
        <child [question]="question" (selected)="onSelect($event)" ></child>
    `
})
export class ParentComponent {
    question: Question;
    constructor() {
        this.question = {
            text: "what is 1+1?",
            choices: [
                { id: 1, name: 'Choice 1'}, 
                { id: 2, name: 'Choice 2'}, 
                { id: 3, name: 'Choice 4'}, 
                { id: 4, name: 'Choice 8'} 
            ]
        };
    }

    onSelect(choice:Choice) {
        alert(choice.id);
    }

}

Hope this helps!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.