Ion-toggle 2 way binding

I’m building settings out in my app, and our Settings page has multiple categories for settings. In order to manage this, my Settings page flows as follows: SettingsPage <uses> ProfileSettingsComponent <uses> SettingsComponent[]. I’m having issues with the child and grandchildren component pieces.

I’m trying to pass in a piece of a settings object into SettingsComponent and have it bind back to the parent. Right now, if I pass in the setting property, all I get back is the value, not the name of the property, nor does the property get updated on the parent.

Let’s get to some code…

ProfileSettingsComponent

import { Component, OnInit } from "@angular/core";
import { SettingsService } from "../../services/settings.service";
import { SettingsKeys } from "../../constants/settings.constants";

@Component({
	selector: "profile-settings",
	template: "profile-settings.component.html",
})
export class ProfileSettingsComponent implements OnInit {

	public settings: ProfileSettings;

	constructor(private _settings: SettingsService) { }

	public ngOnInit() {
		 this.settings = new ProfileSettings(settings[SettingsKeys.Profile] || {})) // returns {email:false, name:false}, etc.
			.then(() => console.log(this.profile, this.settings));
	}

	public updateSettings(e) {
		console.log('Settings.Profile', this.settings); // Eventually persist this back to settings once this.settings actually updates from the child component
	}

profile-settings.component.html

<div class="profile-settings" padding>
	<ion-list *ngIf="settings">
		<setting label="Email" [(setting)]="settings.email" (toggled)="updateSettings($event)"></setting>
	</ion-list>
</div>

setting.component.ts

import { Component, Input, Output, EventEmitter } from "@angular/core";

@Component({
	selector: "setting",
	templateUrl: "setting.component.html"
})
export class SettingComponent {

	@Input() public label: string;
	@Input() public setting: any;
	@Output() public toggled: EventEmitter<any> = new EventEmitter<any>();

	constructor() { }

	public toggle(e) {
		this.toggled.emit(this.setting);
	}

}

setting.component.html

<ion-item>
	<ion-label>
		<h2>{{label}}</h2>
	</ion-label>
	<ion-toggle [(ngModel)]="setting" (ngModelChange)="toggle($event)"></ion-toggle>
</ion-item>

What seemed like the most trivial thing to do in Angular 1 – update a parent property injected into a child component – is extremely difficult. Does anyone have the right direction for me to follow to achieve what I want?

Not sure if it’s related to your underlying problem, but (toggled) is unusual. Normally when doing two-way binding, you name the output property settingChange, i.e. the input property plus “Change”. That way the banana-in-a-box syntax automatically takes care of accepting the changes.

Thanks! I wasn’t aware of any Output() syntatical sugar. Do you think it will work with nested properties, like settings.email?

Can’t think of any reason it wouldn’t.

1 Like