@@ -84,9 +84,9 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
84
84
private onTouched = ( ) => { } ;
85
85
86
86
private _uniqueId : string = `md-slide-toggle-${ ++ nextUniqueId } ` ;
87
- private _checked : boolean = false ;
88
87
private _slideRenderer : SlideToggleRenderer ;
89
88
private _required : boolean = false ;
89
+ private _checked : boolean = false ;
90
90
91
91
/** Reference to the focus state ripple. */
92
92
private _focusRipple : RippleRef | null ;
@@ -103,6 +103,8 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
103
103
/** Whether the label should appear after or before the slide-toggle. Defaults to 'after' */
104
104
@Input ( ) labelPosition : 'before' | 'after' = 'after' ;
105
105
106
+ /** Whether the slide-toggle element is checked or not */
107
+
106
108
/** Used to set the aria-label attribute on the underlying input element. */
107
109
@Input ( 'aria-label' ) ariaLabel : string | null = null ;
108
110
@@ -114,6 +116,13 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
114
116
get required ( ) : boolean { return this . _required ; }
115
117
set required ( value ) { this . _required = coerceBooleanProperty ( value ) ; }
116
118
119
+ /** Whether the slide-toggle element is checked or not */
120
+ @Input ( )
121
+ get checked ( ) : boolean { return this . _checked ; }
122
+ set checked ( value ) {
123
+ this . _checked = ! ! value ;
124
+ this . _changeDetectorRef . markForCheck ( ) ;
125
+ }
117
126
/** An event will be dispatched each time the slide-toggle changes its value. */
118
127
@Output ( ) change : EventEmitter < MdSlideToggleChange > = new EventEmitter < MdSlideToggleChange > ( ) ;
119
128
@@ -147,29 +156,30 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
147
156
}
148
157
149
158
/**
150
- * The onChangeEvent method will be also called on click.
151
- * This is because everything for the slide-toggle is wrapped inside of a label,
152
- * which triggers a onChange event on click.
159
+ * This function will called if the underlying input changed its value through user interaction.
153
160
*/
154
161
_onChangeEvent ( event : Event ) {
155
162
// We always have to stop propagation on the change event.
156
163
// Otherwise the change event, from the input element, will bubble up and
157
164
// emit its event object to the component's `change` output.
158
165
event . stopPropagation ( ) ;
159
166
160
- // Once a drag is currently in progress, we do not want to toggle the slide-toggle on a click.
161
- if ( ! this . disabled && ! this . _slideRenderer . dragging ) {
162
- this . toggle ( ) ;
167
+ // Sync the value from the underlying input element with the slide-toggle component.
168
+ this . checked = this . _inputElement . nativeElement . checked ;
163
169
164
- // Emit our custom change event if the native input emitted one.
165
- // It is important to only emit it, if the native input triggered one, because
166
- // we don't want to trigger a change event, when the `checked` variable changes for example.
167
- this . _emitChangeEvent ( ) ;
168
- }
170
+ // Emit our custom change event if the native input emitted one.
171
+ // It is important to only emit it, if the native input triggered one, because we don't want
172
+ // to trigger a change event, when the `checked` variable changes programmatically.
173
+ this . _emitChangeEvent ( ) ;
169
174
}
170
175
171
176
_onInputClick ( event : Event ) {
172
- this . onTouched ( ) ;
177
+ // In some situations the user will release the mouse on the label element. The label element
178
+ // redirects the click to the underlying input element and will result in a value change.
179
+ // Prevent the default behavior if dragging, because the value will be set after drag.
180
+ if ( this . _slideRenderer . dragging ) {
181
+ event . preventDefault ( ) ;
182
+ }
173
183
174
184
// We have to stop propagation for click events on the visual hidden input element.
175
185
// By default, when a user clicks on a label element, a generated click event will be
@@ -183,7 +193,7 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
183
193
184
194
/** Implemented as part of ControlValueAccessor. */
185
195
writeValue ( value : any ) : void {
186
- this . checked = value ;
196
+ this . checked = ! ! value ;
187
197
}
188
198
189
199
/** Implemented as part of ControlValueAccessor. */
@@ -207,16 +217,6 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
207
217
this . _focusOriginMonitor . focusVia ( this . _inputElement . nativeElement , 'keyboard' ) ;
208
218
}
209
219
210
- /** Whether the slide-toggle is checked. */
211
- @Input ( )
212
- get checked ( ) { return ! ! this . _checked ; }
213
- set checked ( value ) {
214
- if ( this . checked !== ! ! value ) {
215
- this . _checked = value ;
216
- this . onChange ( this . _checked ) ;
217
- }
218
- }
219
-
220
220
/** Toggles the checked state of the slide-toggle. */
221
221
toggle ( ) {
222
222
this . checked = ! this . checked ;
@@ -238,15 +238,17 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
238
238
}
239
239
}
240
240
241
- /** Emits the change event to the `change` output EventEmitter */
241
+ /**
242
+ * Emits a change event on the `change` output. Also notifies the FormControl about the change.
243
+ */
242
244
private _emitChangeEvent ( ) {
243
245
let event = new MdSlideToggleChange ( ) ;
244
246
event . source = this ;
245
247
event . checked = this . checked ;
246
248
this . change . emit ( event ) ;
249
+ this . onChange ( this . checked ) ;
247
250
}
248
251
249
-
250
252
_onDragStart ( ) {
251
253
if ( ! this . disabled ) {
252
254
this . _slideRenderer . startThumbDrag ( this . checked ) ;
0 commit comments