3

I have a proper answer component and i can use it this way

[(answer)]="answer"

It is all okey with fire event and it does work. The Question object contains the Anser[]. And when i try to use it:

<answer *ngFor="let answer of question.Answers" [(answer)]="answer"></answer>

I receive exception

Cannot assign to a reference or variable! ; Zone: ; Task: Promise.then ; Value: Error: Cannot assign to a reference or variable!(…) Error: Cannot assign to a reference or variable!

Anyone have an idea why is throw exception.

answer.component.ts

@Component({
    moduleId: module.id,
    selector: 'answer',
    templateUrl: 'answer.component.html',
})
export class AnswerComponent extends ComponentBase implements OnInit {
    @Input() answer: Answer;
    @Output() answerChange: EventEmitter<Answer> = new EventEmitter<Answer>();

    private _isToggled: boolean;
    @Input() set isToggled(value: boolean) {
        this._isToggled = (value === undefined) ? false : value;  
    }

    get isToggled() {
        return this._isToggled;
    }

    constructor() {
        super();
    }

    ngOnInit() {
        this.requestMaterialDesignUpdate();
    }


    toggle() {
        this.isToggled = !this.isToggled;
        this.requestMaterialDesignUpdate();
    }

    answerTextChanged(input: any) {
        this.answerChange.emit(this.answer);

    }

    markAnswerAsCorrect(event: Event) {
        this.answer.IsCorrect = !this.answer.IsCorrect;
        this.answerChange.emit(this.answer);
    }
}

answer.component.html

<div class="display-flex-nowrap textbookDetailsContainer">
    <div class="padding-2rem answerBorderLeft cursor-pointer width100">
        <header (click)="toggle()" class="answerRowOrder">
            <div>
                <i *ngIf="!isToggled" class="material-icons">arrow_drop_down</i>
                <i *ngIf="isToggled" class="material-icons">arrow_drop_up</i>
            </div>
            <span class="part-text" [innerHTML]="answer.Text"></span>
        </header>
        <div *ngIf="isToggled" class="padding-2rem">
            <ckeditor rows="3" [(ngModel)]="answer.Text" (change)="answerTextChanged($event)" name="answer" [config]="{ extraPlugins: 'justify,image2,divarea',  removePlugins: 'about'}"></ckeditor>
        </div>
    </div>
    <div class="padding-2rem answerBorderRight checkboxBigSize">
        <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect float-left">
            <input type="checkbox" class="mdl-checkbox__input" [checked]="answer.IsCorrect" (change)="markAnswerAsCorrect($event)">
        </label>
    </div>
</div>
10
  • Please post the code for the answer component. Commented Nov 23, 2016 at 9:57
  • Beside your problem, it's not recommended to use double data binding when passing data to child. You should rather use events and register on it from your answer component. like <answer *ngFor="let answer of question.Answers" [answer]="answer" (onAnswerChange)="handleSomeLogicFunction()"></answer> Commented Nov 23, 2016 at 10:14
  • @Günter Zöchbauer updated with code Commented Nov 23, 2016 at 11:16
  • @Maxime For example you can use [(ngModel)] and (change) at the same time. What is going wrong to use for example [(answer)] instead of How to Answer and (answerChange)? And i didn't see any advice in tutorials about passing data to child. Commented Nov 23, 2016 at 11:20
  • 1
    Double data binding is passing data top to bottom and event bottom to top. It's just syntactic sugar for [childProp]="parentProp" (childPropChange)="parentProp = $event" Commented Nov 23, 2016 at 14:03

1 Answer 1

5

This might work

<answer *ngFor="let answer of question.Answers let idx=index"
    [(answer)]="question.Answers[idx]"></answer>
Sign up to request clarification or add additional context in comments.

7 Comments

Sorry, had a redundant s before [idx].answer
I get work it in this way <answer *ngFor="let answer of question.Answers let idx=index" [(answer)]="question.Answers[idx]"></answer>. But why angular didn't understand just simple way [(answer)]="answer"?
Sorry, seems I was a bit sloppy reading your code. [(answer)]="answer" is syntactic sugar for [answer]="answer" (answerChange)="answer = $event" but it is not supported to assign a different value to a *ngFor variable.
I found out that if we input object to child component, we actually send reference of our current object. Than we don't need two-way data binding and we can write <answer *ngFor="let answer of question.Answers" [answer]="answer"></answer>. Every change of answer inside AnswerComponent will change original object.
See a related issue for Angular - Support two-way bindings to the item of ngFor
|

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.