Skip to content

Commit

Permalink
Added the BindablePropertyConfig interface
Browse files Browse the repository at this point in the history
 * describes the configuration object that can be passed to customize
the bindable decorator and the BindableProperty class

 * used the interface type appropriate

 * fixed a few minor typos (spelling)

 * built and ran tests (+1 squashed commits)
  • Loading branch information
aluanhaddad committed Feb 13, 2018
1 parent 64e73f5 commit f72deb0
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 43 deletions.
34 changes: 29 additions & 5 deletions dist/aurelia-templating.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import {
import {
Binding,
createOverrideContext,
bindingMode,
ValueConverterResource,
BindingBehaviorResource,
subscriberCollection,
bindingMode,
ObserverLocator,
EventManager
} from 'aurelia-binding';
Expand Down Expand Up @@ -238,6 +238,30 @@ export declare interface DynamicComponentGetViewStrategy {
getViewStrategy(): string | ViewStrategy;
}

/**
* An optional interface describing the configuration object that can be specified to customize bindable properties.
*/
/**
* An optional interface describing the configuration object that can be specified to customize bindable properties.
*/
export declare interface BindablePropertyConfig {

/**
* The default binding mode of the property.
*/
defaultBindingMode?: bindingMode;

/**
* The name of a view model method to invoke when the property is updated.
*/
changeHandler?: string;

/**
* The name of the property.
*/
name?: string;
}

/**
* Instructs the composition engine how to dynamically compose a component.
*/
Expand Down Expand Up @@ -1673,9 +1697,9 @@ export declare class BindableProperty {

/**
* Creates an instance of BindableProperty.
* @param nameOrConfig The name of the property or a cofiguration object.
* @param nameOrConfig The name of the property or a configuration object.
*/
constructor(nameOrConfig: string | Object);
constructor(nameOrConfig: string | BindablePropertyConfig);

/**
* Registers this bindable property with particular Class and Behavior instance.
Expand Down Expand Up @@ -1876,7 +1900,7 @@ export declare function customElement(name: string): any;
* @param defaultBindingMode The default binding mode to use when the attribute is bound with .bind.
* @param aliases The array of aliases to associate to the custom attribute.
*/
export declare function customAttribute(name: string, defaultBindingMode?: number, aliases?: string[]): any;
export declare function customAttribute(name: string, defaultBindingMode?: bindingMode, aliases?: string[]): any;

/**
* Decorator: Applied to custom attributes. Indicates that whatever element the
Expand All @@ -1889,7 +1913,7 @@ export declare function templateController(target?: any): any;
* Decorator: Specifies that a property is bindable through HTML.
* @param nameOrConfigOrTarget The name of the property, or a configuration object.
*/
export declare function bindable(nameOrConfigOrTarget?: string | Object, key?: any, descriptor?: any): any;
export declare function bindable(nameOrConfigOrTarget?: string | BindablePropertyConfig, key?: any, descriptor?: any): any;

/**
* Decorator: Specifies that the decorated custom attribute has options that
Expand Down
48 changes: 33 additions & 15 deletions dist/aurelia-templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {DOM,PLATFORM,FEATURE} from 'aurelia-pal';
import {relativeToFile} from 'aurelia-path';
import {TemplateRegistryEntry,Loader} from 'aurelia-loader';
import {inject,Container,resolver} from 'aurelia-dependency-injection';
import {Binding,createOverrideContext,ValueConverterResource,BindingBehaviorResource,subscriberCollection,bindingMode,ObserverLocator,EventManager} from 'aurelia-binding';
import {Binding,createOverrideContext,bindingMode,ValueConverterResource,BindingBehaviorResource,subscriberCollection,ObserverLocator,EventManager} from 'aurelia-binding';
import {TaskQueue} from 'aurelia-task-queue';

/**
Expand Down Expand Up @@ -2177,6 +2177,24 @@ interface DynamicComponentGetViewStrategy {
getViewStrategy(): string|ViewStrategy;
}

/**
* An optional interface describing the configuration object that can be specified to customize bindable properties.
*/
interface BindablePropertyConfig {
/**
* The default binding mode of the property.
*/
defaultBindingMode?: bindingMode;
/**
* The name of a view model method to invoke when the property is updated.
*/
changeHandler?: string;
/**
* The name of the property.
*/
name?: string;
}

function getAnimatableElement(view) {
if (view.animatableElement !== undefined) {
return view.animatableElement;
Expand Down Expand Up @@ -4520,9 +4538,9 @@ function getObserver(instance, name) {
export class BindableProperty {
/**
* Creates an instance of BindableProperty.
* @param nameOrConfig The name of the property or a cofiguration object.
* @param nameOrConfig The name of the property or a configuration object.
*/
constructor(nameOrConfig: string | Object) {
constructor(nameOrConfig: string | BindablePropertyConfig) {
if (typeof nameOrConfig === 'string') {
this.name = nameOrConfig;
} else {
Expand Down Expand Up @@ -4706,11 +4724,11 @@ export class BindableProperty {
}

observer = observerLookup[name] = new BehaviorPropertyObserver(
this.owner.taskQueue,
viewModel,
name,
selfSubscriber
);
this.owner.taskQueue,
viewModel,
name,
selfSubscriber
);

Object.defineProperty(viewModel, name, {
configurable: true,
Expand Down Expand Up @@ -5759,7 +5777,7 @@ function validateBehaviorName(name, type) {
* @param instance The resource instance.
*/
export function resource(instance: Object): any {
return function(target) {
return function (target) {
metadata.define(metadata.resource, instance, target);
};
}
Expand Down Expand Up @@ -5796,8 +5814,8 @@ export function customElement(name: string): any {
* @param defaultBindingMode The default binding mode to use when the attribute is bound with .bind.
* @param aliases The array of aliases to associate to the custom attribute.
*/
export function customAttribute(name: string, defaultBindingMode?: number, aliases?: string[]): any {
return function(target) {
export function customAttribute(name: string, defaultBindingMode?: bindingMode, aliases?: string[]): any {
return function (target) {
let r = metadata.getOrCreateOwn(metadata.resource, HtmlBehaviorResource, target);
r.attributeName = validateBehaviorName(name, 'custom attribute');
r.attributeDefaultBindingMode = defaultBindingMode;
Expand All @@ -5823,7 +5841,7 @@ export function templateController(target?): any {
* Decorator: Specifies that a property is bindable through HTML.
* @param nameOrConfigOrTarget The name of the property, or a configuration object.
*/
export function bindable(nameOrConfigOrTarget?: string | Object, key?, descriptor?): any {
export function bindable(nameOrConfigOrTarget?: string | BindablePropertyConfig, key?, descriptor?): any {
let deco = function(target, key2, descriptor2) {
let actualTarget = key2 ? target.constructor : target; //is it on a property or a class?
let r = metadata.getOrCreateOwn(metadata.resource, HtmlBehaviorResource, actualTarget);
Expand Down Expand Up @@ -5929,7 +5947,7 @@ export function processContent(processor: boolean | Function): any {
* element container.
*/
export function containerless(target?): any {
let deco = function(t) {
let deco = function (t) {
let r = metadata.getOrCreateOwn(metadata.resource, HtmlBehaviorResource, t);
r.containerless = true;
};
Expand Down Expand Up @@ -5962,14 +5980,14 @@ export function useView(path: string): any {
* @param dependencies A list of dependencies that the template has.
* @param dependencyBaseUrl A base url from which the dependencies will be loaded.
*/
export function inlineView(markup:string, dependencies?:Array<string|Function|Object>, dependencyBaseUrl?:string): any {
export function inlineView(markup: string, dependencies?: Array<string | Function | Object>, dependencyBaseUrl?: string): any {
return useViewStrategy(new InlineViewStrategy(markup, dependencies, dependencyBaseUrl));
}

/**
* Decorator: Indicates that the component has no view.
*/
export function noView(targetOrDependencies?:Function|Array<any>, dependencyBaseUrl?:string): any {
export function noView(targetOrDependencies?: Function | Array<any>, dependencyBaseUrl?: string): any {
let target;
let dependencies;
if (typeof targetOrDependencies === 'function') {
Expand Down
16 changes: 8 additions & 8 deletions dist/es2015/aurelia-templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { DOM, PLATFORM, FEATURE } from 'aurelia-pal';
import { relativeToFile } from 'aurelia-path';
import { TemplateRegistryEntry, Loader } from 'aurelia-loader';
import { inject, Container, resolver } from 'aurelia-dependency-injection';
import { Binding, createOverrideContext, ValueConverterResource, BindingBehaviorResource, subscriberCollection, bindingMode, ObserverLocator, EventManager } from 'aurelia-binding';
import { Binding, createOverrideContext, bindingMode, ValueConverterResource, BindingBehaviorResource, subscriberCollection, ObserverLocator, EventManager } from 'aurelia-binding';
import { TaskQueue } from 'aurelia-task-queue';

export const animationEvent = {
Expand Down Expand Up @@ -630,7 +630,7 @@ export let ViewLocator = (_temp2 = _class7 = class ViewLocator {
}, _class7.viewStrategyMetadataKey = 'aurelia:view-strategy', _temp2);

function mi(name) {
throw new Error(`BindingLanguage must implement ${ name }().`);
throw new Error(`BindingLanguage must implement ${name}().`);
}

export let BindingLanguage = class BindingLanguage {
Expand Down Expand Up @@ -1060,7 +1060,7 @@ function register(lookup, name, resource, type) {
let existing = lookup[name];
if (existing) {
if (existing !== resource) {
throw new Error(`Attempted to register ${ type } when one with the same name already exists. Name: ${ name }.`);
throw new Error(`Attempted to register ${type} when one with the same name already exists. Name: ${name}.`);
}

return;
Expand Down Expand Up @@ -2998,7 +2998,7 @@ export let ViewEngine = (_dec8 = inject(Loader, Container, ViewCompiler, ModuleA

importIds = dependencies.map(x => x.src);
names = dependencies.map(x => x.name);
logger.debug(`importing resources for ${ registryEntry.address }`, importIds);
logger.debug(`importing resources for ${registryEntry.address}`, importIds);

if (target) {
let viewModelRequires = metadata.get(ViewEngine.viewModelRequireMetadataKey, target);
Expand All @@ -3013,7 +3013,7 @@ export let ViewEngine = (_dec8 = inject(Loader, Container, ViewCompiler, ModuleA
names.push(req.as);
}
}
logger.debug(`importing ViewModel resources for ${ compileInstruction.associatedModuleId }`, importIds.slice(templateImportCount));
logger.debug(`importing ViewModel resources for ${compileInstruction.associatedModuleId}`, importIds.slice(templateImportCount));
}
}

Expand All @@ -3026,7 +3026,7 @@ export let ViewEngine = (_dec8 = inject(Loader, Container, ViewCompiler, ModuleA
let resourceModule = this.moduleAnalyzer.analyze(normalizedId, viewModelModule, moduleMember);

if (!resourceModule.mainResource) {
throw new Error(`No view model found in module "${ moduleImport }".`);
throw new Error(`No view model found in module "${moduleImport}".`);
}

resourceModule.initialize(this.container);
Expand Down Expand Up @@ -3442,7 +3442,7 @@ export let BindableProperty = class BindableProperty {
} else if ('propertyChanged' in viewModel) {
selfSubscriber = (newValue, oldValue) => viewModel.propertyChanged(name, newValue, oldValue);
} else if (changeHandlerName !== null) {
throw new Error(`Change handler ${ changeHandlerName } was specified but not declared on the class.`);
throw new Error(`Change handler ${changeHandlerName} was specified but not declared on the class.`);
}

if (defaultValue !== undefined) {
Expand Down Expand Up @@ -4353,7 +4353,7 @@ export let ElementConfigResource = class ElementConfigResource {
function validateBehaviorName(name, type) {
if (/[A-Z]/.test(name)) {
let newName = _hyphenate(name);
LogManager.getLogger('templating').warn(`'${ name }' is not a valid ${ type } name and has been converted to '${ newName }'. Upper-case letters are not allowed because the DOM is not case-sensitive.`);
LogManager.getLogger('templating').warn(`'${name}' is not a valid ${type} name and has been converted to '${newName}'. Upper-case letters are not allowed because the DOM is not case-sensitive.`);
return newName;
}
return name;
Expand Down
2 changes: 1 addition & 1 deletion dist/native-modules/aurelia-templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { DOM, PLATFORM, FEATURE } from 'aurelia-pal';
import { relativeToFile } from 'aurelia-path';
import { TemplateRegistryEntry, Loader } from 'aurelia-loader';
import { inject, Container, resolver } from 'aurelia-dependency-injection';
import { Binding, createOverrideContext, ValueConverterResource, BindingBehaviorResource, subscriberCollection, bindingMode, ObserverLocator, EventManager } from 'aurelia-binding';
import { Binding, createOverrideContext, bindingMode, ValueConverterResource, BindingBehaviorResource, subscriberCollection, ObserverLocator, EventManager } from 'aurelia-binding';
import { TaskQueue } from 'aurelia-task-queue';

export var animationEvent = {
Expand Down
4 changes: 2 additions & 2 deletions dist/system/aurelia-templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
System.register(['aurelia-logging', 'aurelia-metadata', 'aurelia-pal', 'aurelia-path', 'aurelia-loader', 'aurelia-dependency-injection', 'aurelia-binding', 'aurelia-task-queue'], function (_export, _context) {
"use strict";

var LogManager, metadata, Origin, protocol, DOM, PLATFORM, FEATURE, relativeToFile, TemplateRegistryEntry, Loader, inject, Container, resolver, Binding, createOverrideContext, ValueConverterResource, BindingBehaviorResource, subscriberCollection, bindingMode, ObserverLocator, EventManager, TaskQueue, _createClass, _typeof, _class, _temp, _dec, _class2, _dec2, _class3, _dec3, _class4, _dec4, _class5, _dec5, _class6, _class7, _temp2, _dec6, _class8, _class9, _temp3, _class11, _dec7, _class13, _dec8, _class14, _class15, _temp4, _dec9, _class16, _dec10, _class17, _dec11, _class18, animationEvent, Animator, CompositionTransactionNotifier, CompositionTransactionOwnershipToken, CompositionTransaction, capitalMatcher, ViewEngineHooksResource, ElementEvents, EventHandlerImpl, ResourceLoadContext, ViewCompileInstruction, BehaviorInstruction, TargetInstruction, viewStrategy, RelativeViewStrategy, ConventionalViewStrategy, NoViewStrategy, TemplateRegistryViewStrategy, InlineViewStrategy, ViewLocator, BindingLanguage, noNodes, SlotCustomAttribute, PassThroughSlot, ShadowSlot, ShadowDOM, ViewResources, View, ViewSlot, ProviderResolver, providerResolverInstance, BoundViewFactory, ViewFactory, nextInjectorId, lastAUTargetID, ViewCompiler, ResourceModule, ResourceDescription, ModuleAnalyzer, logger, ProxyViewFactory, auSlotBehavior, ViewEngine, Controller, BehaviorPropertyObserver, BindableProperty, lastProviderId, HtmlBehaviorResource, ChildObserver, noMutations, ChildObserverBinder, SwapStrategies, CompositionEngine, ElementConfigResource, defaultShadowDOMOptions, TemplatingEngine;
var LogManager, metadata, Origin, protocol, DOM, PLATFORM, FEATURE, relativeToFile, TemplateRegistryEntry, Loader, inject, Container, resolver, Binding, createOverrideContext, bindingMode, ValueConverterResource, BindingBehaviorResource, subscriberCollection, ObserverLocator, EventManager, TaskQueue, _createClass, _typeof, _class, _temp, _dec, _class2, _dec2, _class3, _dec3, _class4, _dec4, _class5, _dec5, _class6, _class7, _temp2, _dec6, _class8, _class9, _temp3, _class11, _dec7, _class13, _dec8, _class14, _class15, _temp4, _dec9, _class16, _dec10, _class17, _dec11, _class18, animationEvent, Animator, CompositionTransactionNotifier, CompositionTransactionOwnershipToken, CompositionTransaction, capitalMatcher, ViewEngineHooksResource, ElementEvents, EventHandlerImpl, ResourceLoadContext, ViewCompileInstruction, BehaviorInstruction, TargetInstruction, viewStrategy, RelativeViewStrategy, ConventionalViewStrategy, NoViewStrategy, TemplateRegistryViewStrategy, InlineViewStrategy, ViewLocator, BindingLanguage, noNodes, SlotCustomAttribute, PassThroughSlot, ShadowSlot, ShadowDOM, ViewResources, View, ViewSlot, ProviderResolver, providerResolverInstance, BoundViewFactory, ViewFactory, nextInjectorId, lastAUTargetID, ViewCompiler, ResourceModule, ResourceDescription, ModuleAnalyzer, logger, ProxyViewFactory, auSlotBehavior, ViewEngine, Controller, BehaviorPropertyObserver, BindableProperty, lastProviderId, HtmlBehaviorResource, ChildObserver, noMutations, ChildObserverBinder, SwapStrategies, CompositionEngine, ElementConfigResource, defaultShadowDOMOptions, TemplatingEngine;



Expand Down Expand Up @@ -735,10 +735,10 @@ System.register(['aurelia-logging', 'aurelia-metadata', 'aurelia-pal', 'aurelia-
}, function (_aureliaBinding) {
Binding = _aureliaBinding.Binding;
createOverrideContext = _aureliaBinding.createOverrideContext;
bindingMode = _aureliaBinding.bindingMode;
ValueConverterResource = _aureliaBinding.ValueConverterResource;
BindingBehaviorResource = _aureliaBinding.BindingBehaviorResource;
subscriberCollection = _aureliaBinding.subscriberCollection;
bindingMode = _aureliaBinding.bindingMode;
ObserverLocator = _aureliaBinding.ObserverLocator;
EventManager = _aureliaBinding.EventManager;
}, function (_aureliaTaskQueue) {
Expand Down
14 changes: 7 additions & 7 deletions src/bindable-property.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ function getObserver(instance, name) {
export class BindableProperty {
/**
* Creates an instance of BindableProperty.
* @param nameOrConfig The name of the property or a cofiguration object.
* @param nameOrConfig The name of the property or a configuration object.
*/
constructor(nameOrConfig: string | Object) {
constructor(nameOrConfig: string | BindablePropertyConfig) {
if (typeof nameOrConfig === 'string') {
this.name = nameOrConfig;
} else {
Expand Down Expand Up @@ -219,11 +219,11 @@ export class BindableProperty {
}

observer = observerLookup[name] = new BehaviorPropertyObserver(
this.owner.taskQueue,
viewModel,
name,
selfSubscriber
);
this.owner.taskQueue,
viewModel,
name,
selfSubscriber
);

Object.defineProperty(viewModel, name, {
configurable: true,
Expand Down
10 changes: 5 additions & 5 deletions src/decorators.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function customElement(name: string): any {
* @param defaultBindingMode The default binding mode to use when the attribute is bound with .bind.
* @param aliases The array of aliases to associate to the custom attribute.
*/
export function customAttribute(name: string, defaultBindingMode?: number, aliases?: string[]): any {
export function customAttribute(name: string, defaultBindingMode?: bindingMode, aliases?: string[]): any {
return function(target) {
let r = metadata.getOrCreateOwn(metadata.resource, HtmlBehaviorResource, target);
r.attributeName = validateBehaviorName(name, 'custom attribute');
Expand All @@ -85,7 +85,7 @@ export function templateController(target?): any {
* Decorator: Specifies that a property is bindable through HTML.
* @param nameOrConfigOrTarget The name of the property, or a configuration object.
*/
export function bindable(nameOrConfigOrTarget?: string | Object, key?, descriptor?): any {
export function bindable(nameOrConfigOrTarget?: string | BindablePropertyConfig, key?, descriptor?): any {
let deco = function(target, key2, descriptor2) {
let actualTarget = key2 ? target.constructor : target; //is it on a property or a class?
let r = metadata.getOrCreateOwn(metadata.resource, HtmlBehaviorResource, actualTarget);
Expand Down Expand Up @@ -191,7 +191,7 @@ export function processContent(processor: boolean | Function): any {
* element container.
*/
export function containerless(target?): any {
let deco = function(t) {
let deco = function (t) {
let r = metadata.getOrCreateOwn(metadata.resource, HtmlBehaviorResource, t);
r.containerless = true;
};
Expand Down Expand Up @@ -224,14 +224,14 @@ export function useView(path: string): any {
* @param dependencies A list of dependencies that the template has.
* @param dependencyBaseUrl A base url from which the dependencies will be loaded.
*/
export function inlineView(markup:string, dependencies?:Array<string|Function|Object>, dependencyBaseUrl?:string): any {
export function inlineView(markup: string, dependencies?: Array<string | Function | Object>, dependencyBaseUrl?: string): any {
return useViewStrategy(new InlineViewStrategy(markup, dependencies, dependencyBaseUrl));
}

/**
* Decorator: Indicates that the component has no view.
*/
export function noView(targetOrDependencies?:Function|Array<any>, dependencyBaseUrl?:string): any {
export function noView(targetOrDependencies?: Function | Array<any>, dependencyBaseUrl?: string): any {
let target;
let dependencies;
if (typeof targetOrDependencies === 'function') {
Expand Down
Loading

0 comments on commit f72deb0

Please sign in to comment.