feat(view): reimplemented property setters using change detection
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
import {Component, View} from 'angular2/angular2';
|
||||
import {PropertySetter, EventEmitter} from 'angular2/src/core/annotations/di';
|
||||
import {onChange} from 'angular2/src/core/annotations/annotations';
|
||||
import {isPresent, StringWrapper} from 'angular2/src/facade/lang';
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
|
||||
|
||||
@Component({selector: '[md-button]:not([href])'})
|
||||
@ -17,21 +16,18 @@ export class MdButton {
|
||||
'disabled': 'disabled'
|
||||
},
|
||||
hostListeners: {'click': 'onClick($event)'},
|
||||
hostProperties: {'tabIndex': 'tabIndex'},
|
||||
lifecycle: [onChange]
|
||||
})
|
||||
@View({
|
||||
templateUrl: 'angular2_material/src/components/button/button.html'
|
||||
})
|
||||
export class MdAnchor {
|
||||
tabIndexSetter: Function;
|
||||
tabIndex: number;
|
||||
|
||||
/** Whether the component is disabled. */
|
||||
disabled: boolean;
|
||||
|
||||
constructor(@PropertySetter('tabIndex') tabIndexSetter: Function) {
|
||||
this.tabIndexSetter = tabIndexSetter;
|
||||
}
|
||||
|
||||
onClick(event) {
|
||||
// A disabled anchor shouldn't navigate anywhere.
|
||||
if (isPresent(this.disabled) && this.disabled !== false) {
|
||||
@ -42,6 +38,6 @@ export class MdAnchor {
|
||||
/** Invoked when a change is detected. */
|
||||
onChange(_) {
|
||||
// A disabled anchor should not be in the tab flow.
|
||||
this.tabIndexSetter(this.disabled ? -1 : 0);
|
||||
this.tabIndex = this.disabled ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Component, View, Attribute, PropertySetter} from 'angular2/angular2';
|
||||
import {Component, View, Attribute} from 'angular2/angular2';
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {KEY_SPACE} from 'angular2_material/src/core/constants'
|
||||
import {KeyboardEvent} from 'angular2/src/facade/browser';
|
||||
@ -11,6 +11,12 @@ import {KeyboardEvent} from 'angular2/src/facade/browser';
|
||||
},
|
||||
hostListeners: {
|
||||
'keydown': 'onKeydown($event)'
|
||||
},
|
||||
hostProperties: {
|
||||
'tabindex': 'tabindex',
|
||||
'role': 'attr.role',
|
||||
'checked': 'attr.aria-checked',
|
||||
'disabled_': 'attr.aria-disabled'
|
||||
}
|
||||
})
|
||||
@View({
|
||||
@ -19,38 +25,21 @@ import {KeyboardEvent} from 'angular2/src/facade/browser';
|
||||
})
|
||||
export class MdCheckbox {
|
||||
/** Whether this checkbox is checked. */
|
||||
checked_: boolean;
|
||||
checked: boolean;
|
||||
|
||||
/** Whether this checkbox is disabled. */
|
||||
disabled_: boolean;
|
||||
|
||||
/** Setter for `aria-checked` attribute. */
|
||||
ariaCheckedSetter: Function;
|
||||
/** Setter for `role` attribute. */
|
||||
role: string;
|
||||
|
||||
/** Setter for `aria-disabled` attribute. */
|
||||
ariaDisabledSetter: Function;
|
||||
/** Setter for tabindex */
|
||||
tabindex: any;
|
||||
|
||||
constructor(
|
||||
@Attribute('tabindex') tabindex: string,
|
||||
@PropertySetter('tabindex') tabindexSetter: Function,
|
||||
@PropertySetter('attr.role') roleSetter: Function,
|
||||
@PropertySetter('attr.aria-checked') ariaCheckedSetter: Function,
|
||||
@PropertySetter('attr.aria-disabled') ariaDisabledSetter: Function) {
|
||||
this.ariaCheckedSetter = ariaCheckedSetter;
|
||||
this.ariaDisabledSetter = ariaDisabledSetter;
|
||||
|
||||
roleSetter('checkbox');
|
||||
constructor(@Attribute('tabindex') tabindex: string) {
|
||||
this.role = 'checkbox';
|
||||
this.checked = false;
|
||||
tabindexSetter(isPresent(tabindex) ? tabindex : '0');
|
||||
}
|
||||
|
||||
get checked() {
|
||||
return this.checked_;
|
||||
}
|
||||
|
||||
set checked(value) {
|
||||
this.checked_ = value;
|
||||
this.ariaCheckedSetter(value);
|
||||
this.tabindex = isPresent(tabindex) ? tabindex : '0';
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
@ -59,7 +48,6 @@ export class MdCheckbox {
|
||||
|
||||
set disabled(value) {
|
||||
this.disabled_ = isPresent(value) && value !== false;
|
||||
this.ariaDisabledSetter(this.disabled_);
|
||||
}
|
||||
|
||||
onKeydown(event: KeyboardEvent) {
|
||||
@ -76,6 +64,5 @@ export class MdCheckbox {
|
||||
}
|
||||
|
||||
this.checked = !this.checked;
|
||||
this.ariaCheckedSetter(this.checked);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import {Component, View, onAllChangesDone, Parent} from 'angular2/angular2';
|
||||
import {onDestroy, onChange} from 'angular2/src/core/annotations/annotations';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {isPresent, isString, NumberWrapper, stringify} from 'angular2/src/facade/lang';
|
||||
import {PropertySetter} from 'angular2/src/core/annotations/di';
|
||||
|
||||
// TODO(jelbourn): Set appropriate aria attributes for grid list elements.
|
||||
|
||||
@ -172,6 +171,15 @@ export class MdGridList {
|
||||
'rowspan': 'rowspan',
|
||||
'colspan': 'colspan'
|
||||
},
|
||||
hostProperties: {
|
||||
'styleHeight': 'style.height',
|
||||
'styleWidth': 'style.width',
|
||||
'styleTop': 'style.top',
|
||||
'styleLeft': 'style.left',
|
||||
'styleMarginTop': 'style.marginTop',
|
||||
'stylePaddingTop': 'style.paddingTop',
|
||||
'role': 'role'
|
||||
},
|
||||
lifecycle: [onDestroy, onChange]
|
||||
})
|
||||
@View({
|
||||
@ -181,40 +189,28 @@ export class MdGridTile {
|
||||
gridList: MdGridList;
|
||||
rowspan: number;
|
||||
colspan: number;
|
||||
heightSetter;
|
||||
widthSetter;
|
||||
topSetter;
|
||||
leftSetter;
|
||||
marginTopSetter;
|
||||
paddingTopSetter;
|
||||
|
||||
styleHeight:any;
|
||||
styleWidth:any;
|
||||
styleTop:any;
|
||||
styleLeft:any;
|
||||
styleMarginTop:any;
|
||||
stylePaddingTop:any;
|
||||
role:any;
|
||||
|
||||
isRegisteredWithGridList: boolean;
|
||||
|
||||
constructor(
|
||||
@Parent() gridList: MdGridList,
|
||||
@PropertySetter('style.height') heightSetter: Function,
|
||||
@PropertySetter('style.width') widthSetter: Function,
|
||||
@PropertySetter('style.top') topSetter: Function,
|
||||
@PropertySetter('style.left') leftSetter: Function,
|
||||
@PropertySetter('style.marginTop') marginTopSetter: Function,
|
||||
@PropertySetter('style.paddingTop') paddingTopSetter: Function,
|
||||
@PropertySetter('role') roleSetter: Function
|
||||
) {
|
||||
constructor(@Parent() gridList: MdGridList) {
|
||||
this.gridList = gridList;
|
||||
this.heightSetter = heightSetter;
|
||||
this.widthSetter = widthSetter;
|
||||
this.topSetter = topSetter;
|
||||
this.leftSetter = leftSetter;
|
||||
this.marginTopSetter = marginTopSetter;
|
||||
this.paddingTopSetter = paddingTopSetter;
|
||||
roleSetter('listitem');
|
||||
|
||||
this.role = 'listitem';
|
||||
|
||||
// Tiles default to 1x1, but rowspan and colspan can be changed via binding.
|
||||
this.rowspan = 1;
|
||||
this.colspan = 1;
|
||||
|
||||
// DEBUG
|
||||
heightSetter(`${gridList.tiles.length * 100}px`);
|
||||
this.styleHeight = `${gridList.tiles.length * 100}px`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Component, View, Attribute, PropertySetter, onChange} from 'angular2/angular2';
|
||||
import {Component, View, Attribute, onChange} from 'angular2/angular2';
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {Math} from 'angular2/src/facade/math';
|
||||
|
||||
@ -8,6 +8,12 @@ import {Math} from 'angular2/src/facade/math';
|
||||
properties: {
|
||||
'value': 'value',
|
||||
'bufferValue': 'buffer-value'
|
||||
},
|
||||
hostProperties: {
|
||||
'role': 'attr.role',
|
||||
'ariaValuemin': 'attr.aria-valuemin',
|
||||
'ariaValuemax': 'attr.aria-valuemax',
|
||||
'ariaValuenow': 'attr.aria-valuenow'
|
||||
}
|
||||
})
|
||||
@View({
|
||||
@ -33,19 +39,20 @@ export class MdProgressLinear {
|
||||
/** CSS `transform` property applied to the secondary bar. */
|
||||
secondaryBarTransform: string;
|
||||
|
||||
constructor(
|
||||
@Attribute('md-mode') mode: string,
|
||||
@PropertySetter('attr.role') roleSetter: Function,
|
||||
@PropertySetter('attr.aria-valuemin') ariaValueMinSetter: Function,
|
||||
@PropertySetter('attr.aria-valuemax') ariaValueMaxSetter: Function,
|
||||
@PropertySetter('attr.aria-valuenow') ariaValueNowSetter: Function) {
|
||||
|
||||
role:any;
|
||||
ariaValuemin:any;
|
||||
ariaValuemax:any;
|
||||
ariaValuenow:any;
|
||||
|
||||
constructor(@Attribute('md-mode') mode: string) {
|
||||
this.ariaValueNowSetter = ariaValueNowSetter;
|
||||
this.primaryBarTransform = '';
|
||||
this.secondaryBarTransform = '';
|
||||
|
||||
roleSetter('progressbar');
|
||||
ariaValueMinSetter('0');
|
||||
ariaValueMaxSetter('100');
|
||||
this.role = 'progressbar';
|
||||
this.ariaValuemin = '0';
|
||||
this.ariaValuemax = '100';
|
||||
|
||||
this.mode = isPresent(mode) ? mode : Mode.DETERMINATE;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Component, View, Parent, Ancestor, Attribute, PropertySetter} from 'angular2/angular2';
|
||||
import {Component, View, Parent, Ancestor, Attribute} from 'angular2/angular2';
|
||||
import {Optional} from 'angular2/src/di/annotations';
|
||||
import {MdRadioDispatcher} from 'angular2_material/src/components/radio/radio_dispatcher'
|
||||
import {onChange} from 'angular2/src/core/annotations/annotations';
|
||||
@ -34,6 +34,13 @@ var _uniqueIdCounter:number = 0;
|
||||
},
|
||||
hostListeners: {
|
||||
'keydown': 'onKeydown($event)'
|
||||
},
|
||||
hostProperties: {
|
||||
'id': 'id',
|
||||
'tabindex': 'tabindex',
|
||||
'role': 'attr.role',
|
||||
'checked': 'attr.aria-checked',
|
||||
'disabled': 'attr.aria-disabled'
|
||||
}
|
||||
})
|
||||
@View({
|
||||
@ -42,7 +49,7 @@ var _uniqueIdCounter:number = 0;
|
||||
})
|
||||
export class MdRadioButton {
|
||||
/** Whether this radio is checked. */
|
||||
checked_: boolean;
|
||||
checked: boolean;
|
||||
|
||||
/** Whether the radio is disabled. */
|
||||
disabled_: boolean;
|
||||
@ -62,36 +69,26 @@ export class MdRadioButton {
|
||||
/** Dispatcher for coordinating radio unique-selection by name. */
|
||||
radioDispatcher: MdRadioDispatcher;
|
||||
|
||||
/** Setter for `aria-checked` attribute. */
|
||||
ariaCheckedSetter: Function;
|
||||
|
||||
/** Setter for `aria-disabled` attribute. */
|
||||
ariaDisabledSetter: Function;
|
||||
tabindex:any;
|
||||
|
||||
role:any;
|
||||
|
||||
constructor(
|
||||
@Optional() @Parent() radioGroup: MdRadioGroup,
|
||||
@Attribute('id') id: string,
|
||||
@Attribute('tabindex') tabindex: string,
|
||||
@PropertySetter('id') idSetter: Function,
|
||||
@PropertySetter('tabindex') tabindexSetter: Function,
|
||||
@PropertySetter('attr.role') roleSetter: Function,
|
||||
@PropertySetter('attr.aria-checked') ariaCheckedSetter: Function,
|
||||
@PropertySetter('attr.aria-disabled') ariaDisabledSetter: Function,
|
||||
radioDispatcher: MdRadioDispatcher) {
|
||||
// Assertions. Ideally these should be stripped out by the compiler.
|
||||
// TODO(jelbourn): Assert that there's no name binding AND a parent radio group.
|
||||
|
||||
this.radioGroup = radioGroup;
|
||||
this.radioDispatcher = radioDispatcher;
|
||||
this.ariaCheckedSetter = ariaCheckedSetter;
|
||||
this.ariaDisabledSetter = ariaDisabledSetter;
|
||||
this.value = null;
|
||||
|
||||
roleSetter('radio');
|
||||
this.role = 'radio';
|
||||
this.checked = false;
|
||||
|
||||
this.id = isPresent(id) ? id : `md-radio-${_uniqueIdCounter++}`;
|
||||
idSetter(this.id);
|
||||
this.id = isPresent(id) ? id : `md-radio-${_uniqueIdCounter++}`;;
|
||||
|
||||
// Whenever a radio button with the same name is checked, uncheck this radio button.
|
||||
radioDispatcher.listen((name) => {
|
||||
@ -108,7 +105,7 @@ export class MdRadioButton {
|
||||
|
||||
// If the user has not set a tabindex, default to zero (in the normal document flow).
|
||||
if (!isPresent(radioGroup)) {
|
||||
tabindexSetter(isPresent(tabindex) ? tabindex : '0');
|
||||
this.tabindex = isPresent(tabindex) ? tabindex : '0';
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,22 +126,12 @@ export class MdRadioButton {
|
||||
(isPresent(this.radioGroup) && this.radioGroup.disabled);
|
||||
}
|
||||
|
||||
get checked() {
|
||||
return this.checked_;
|
||||
}
|
||||
|
||||
set checked(value) {
|
||||
this.checked_ = value;
|
||||
this.ariaCheckedSetter(value);
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return this.disabled_;
|
||||
}
|
||||
|
||||
set disabled(value) {
|
||||
this.disabled_ = isPresent(value) && value !== false;
|
||||
this.ariaDisabledSetter(this.disabled_);
|
||||
}
|
||||
|
||||
/** Select this radio button. */
|
||||
@ -183,6 +170,13 @@ export class MdRadioButton {
|
||||
},
|
||||
hostListeners: {
|
||||
'keydown': 'onKeydown($event)'
|
||||
},
|
||||
hostProperties: {
|
||||
'tabindex': 'tabindex',
|
||||
'role': 'attr.role',
|
||||
'checked': 'attr.aria-checked',
|
||||
'disabled': 'attr.aria-disabled',
|
||||
'activedescendant': 'attr.aria-activedescendant'
|
||||
}
|
||||
})
|
||||
@View({
|
||||
@ -201,11 +195,7 @@ export class MdRadioGroup {
|
||||
/** List of child radio buttons. */
|
||||
radios_: List<MdRadioButton>;
|
||||
|
||||
changeEmitter: Function;
|
||||
|
||||
ariaActiveDescendantSetter: Function;
|
||||
|
||||
ariaDisabledSetter: Function;
|
||||
activedescendant: any;
|
||||
|
||||
disabled_: boolean;
|
||||
|
||||
@ -214,30 +204,28 @@ export class MdRadioGroup {
|
||||
|
||||
change:EventEmitter;
|
||||
|
||||
tabindex:any;
|
||||
|
||||
role:any;
|
||||
|
||||
constructor(
|
||||
@Attribute('tabindex') tabindex: string,
|
||||
@Attribute('disabled') disabled: string,
|
||||
@PropertySetter('tabindex') tabindexSetter: Function,
|
||||
@PropertySetter('attr.role') roleSetter: Function,
|
||||
@PropertySetter('attr.aria-disabled') ariaDisabledSetter: Function,
|
||||
@PropertySetter('attr.aria-activedescendant') ariaActiveDescendantSetter: Function,
|
||||
radioDispatcher: MdRadioDispatcher) {
|
||||
this.name_ = `md-radio-group-${_uniqueIdCounter++}`;
|
||||
this.radios_ = [];
|
||||
this.change = new EventEmitter();
|
||||
this.ariaActiveDescendantSetter = ariaActiveDescendantSetter;
|
||||
this.ariaDisabledSetter = ariaDisabledSetter;
|
||||
this.radioDispatcher = radioDispatcher;
|
||||
this.selectedRadioId = '';
|
||||
this.disabled_ = false;
|
||||
|
||||
roleSetter('radiogroup');
|
||||
this.role = 'radiogroup';
|
||||
|
||||
// The simple presence of the `disabled` attribute dictates disabled state.
|
||||
this.disabled = isPresent(disabled);
|
||||
|
||||
// If the user has not set a tabindex, default to zero (in the normal document flow).
|
||||
tabindexSetter(isPresent(tabindex) ? tabindex : '0');
|
||||
this.tabindex = isPresent(tabindex) ? tabindex : '0';
|
||||
}
|
||||
|
||||
/** Gets the name of this group, as to be applied in the HTML 'name' attribute. */
|
||||
@ -251,7 +239,6 @@ export class MdRadioGroup {
|
||||
|
||||
set disabled(value) {
|
||||
this.disabled_ = isPresent(value) && value !== false;
|
||||
this.ariaDisabledSetter(this.disabled_);
|
||||
}
|
||||
|
||||
/** Change handler invoked when bindings are resolved or when bindings have changed. */
|
||||
@ -267,7 +254,7 @@ export class MdRadioGroup {
|
||||
if (radio.value == this.value) {
|
||||
radio.checked = true;
|
||||
this.selectedRadioId = radio.id;
|
||||
this.ariaActiveDescendantSetter(radio.id);
|
||||
this.activedescendant = radio.id;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -277,7 +264,7 @@ export class MdRadioGroup {
|
||||
updateValue(value: any, id: string) {
|
||||
this.value = value;
|
||||
this.selectedRadioId = id;
|
||||
this.ariaActiveDescendantSetter(id);
|
||||
this.activedescendant = id;
|
||||
ObservableWrapper.callNext(this.change, null);
|
||||
}
|
||||
|
||||
@ -335,6 +322,6 @@ export class MdRadioGroup {
|
||||
|
||||
this.value = radio.value;
|
||||
this.selectedRadioId = radio.id;
|
||||
this.ariaActiveDescendantSetter(radio.id);
|
||||
this.activedescendant = radio.id;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Component, View, Attribute, PropertySetter} from 'angular2/angular2';
|
||||
import {Component, View, Attribute} from 'angular2/angular2';
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {KEY_SPACE} from 'angular2_material/src/core/constants'
|
||||
import {KeyboardEvent} from 'angular2/src/facade/browser';
|
||||
@ -13,6 +13,11 @@ import {KeyboardEvent} from 'angular2/src/facade/browser';
|
||||
},
|
||||
hostListeners: {
|
||||
'keydown': 'onKeydown($event)'
|
||||
},
|
||||
hostProperties: {
|
||||
'checked': 'attr.aria-checked',
|
||||
'disabled_': 'attr.aria-disabled',
|
||||
'role': 'attr.role'
|
||||
}
|
||||
})
|
||||
@View({
|
||||
@ -21,38 +26,18 @@ import {KeyboardEvent} from 'angular2/src/facade/browser';
|
||||
})
|
||||
export class MdSwitch {
|
||||
/** Whether this switch is checked. */
|
||||
checked_: boolean;
|
||||
checked: boolean;
|
||||
|
||||
/** Whether this switch is disabled. */
|
||||
disabled_: boolean;
|
||||
|
||||
/** Setter for `aria-checked` attribute. */
|
||||
ariaCheckedSetter: Function;
|
||||
tabindex:any;
|
||||
role:any;
|
||||
|
||||
/** Setter for `aria-disabled` attribute. */
|
||||
ariaDisabledSetter: Function;
|
||||
|
||||
constructor(
|
||||
@Attribute('tabindex') tabindex: string,
|
||||
@PropertySetter('tabindex') tabindexSetter: Function,
|
||||
@PropertySetter('attr.role') roleSetter: Function,
|
||||
@PropertySetter('attr.aria-checked') ariaCheckedSetter: Function,
|
||||
@PropertySetter('attr.aria-disabled') ariaDisabledSetter: Function) {
|
||||
this.ariaCheckedSetter = ariaCheckedSetter;
|
||||
this.ariaDisabledSetter = ariaDisabledSetter;
|
||||
|
||||
roleSetter('checkbox');
|
||||
constructor(@Attribute('tabindex') tabindex: string) {
|
||||
this.role = 'checkbox';
|
||||
this.checked = false;
|
||||
tabindexSetter(isPresent(tabindex) ? tabindex : '0');
|
||||
}
|
||||
|
||||
get checked() {
|
||||
return this.checked_;
|
||||
}
|
||||
|
||||
set checked(value) {
|
||||
this.checked_ = value;
|
||||
this.ariaCheckedSetter(value);
|
||||
this.tabindex = isPresent(tabindex) ? tabindex : '0';
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
@ -61,7 +46,6 @@ export class MdSwitch {
|
||||
|
||||
set disabled(value) {
|
||||
this.disabled_ = isPresent(value) && value !== false;
|
||||
this.ariaDisabledSetter(this.disabled_);
|
||||
}
|
||||
|
||||
onKeydown(event: KeyboardEvent) {
|
||||
@ -78,7 +62,6 @@ export class MdSwitch {
|
||||
}
|
||||
|
||||
this.checked = !this.checked;
|
||||
this.ariaCheckedSetter(this.checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user