mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Fix setting text property to number. (#3449)
Fix setting JS property from native.
This commit is contained in:
@@ -2,6 +2,7 @@ import { unsetValue } from "ui/core/dependency-observable";
|
||||
import { WrappedValue } from "data/observable";
|
||||
import { ViewBase } from "./view-base";
|
||||
import { Style } from "ui/styling/style";
|
||||
import * as definitions from "ui/core/view-base";
|
||||
|
||||
export { unsetValue, Style };
|
||||
|
||||
@@ -31,44 +32,21 @@ const enum ValueSource {
|
||||
Local = 3
|
||||
}
|
||||
|
||||
export interface PropertyOptions<T, U> {
|
||||
name: string;
|
||||
defaultValue?: U;
|
||||
affectsLayout?: boolean;
|
||||
equalityComparer?(this: void, x: U, y: U): boolean;
|
||||
valueChanged?(this: void, target: T, oldValue: U, newValue: U): void;
|
||||
valueConverter?(this: void, value: string): U;
|
||||
}
|
||||
|
||||
export interface CoerciblePropertyOptions<T, U> extends PropertyOptions<T, U> {
|
||||
readonly coerceValue: (t: T, u: U) => U;
|
||||
}
|
||||
|
||||
export interface ShorthandPropertyOptions<P> {
|
||||
name: string;
|
||||
cssName: string;
|
||||
converter(this: void, value: string | P): [CssProperty<any, any>, any][];
|
||||
getter(this: Style): string | P;
|
||||
}
|
||||
|
||||
export interface CssPropertyOptions<T extends Style, U> extends PropertyOptions<T, U> {
|
||||
cssName: string;
|
||||
}
|
||||
|
||||
export class Property<T extends ViewBase, U> implements PropertyDescriptor {
|
||||
export class Property<T extends ViewBase, U> implements PropertyDescriptor, definitions.Property<T, U> {
|
||||
private registered: boolean;
|
||||
private readonly name: string;
|
||||
public readonly key: symbol;
|
||||
public readonly native: symbol;
|
||||
public readonly defaultValueKey: symbol;
|
||||
public readonly defaultValue: U;
|
||||
public readonly nativeValueChange: (owner: T, value: U) => void;
|
||||
|
||||
public get: () => U;
|
||||
public set: (value: U) => void;
|
||||
public enumerable: boolean = true;
|
||||
public configurable: boolean = true;
|
||||
|
||||
constructor(options: PropertyOptions<T, U>) {
|
||||
constructor(options: definitions.PropertyOptions<T, U>) {
|
||||
const name = options.name;
|
||||
this.name = name;
|
||||
|
||||
@@ -85,12 +63,12 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor {
|
||||
this.defaultValue = defaultValue;
|
||||
|
||||
const eventName = name + "Change";
|
||||
const affectsLayout: boolean = options.affectsLayout;
|
||||
const equalityComparer = options.equalityComparer;
|
||||
const affectsLayout: boolean = options.affectsLayout;
|
||||
const valueChanged = options.valueChanged;
|
||||
const valueConverter = options.valueConverter;
|
||||
|
||||
this.set = function (this: T, value: any): void {
|
||||
this.set = function (this: T, value: U): void {
|
||||
const reset = value === unsetValue;
|
||||
let unboxedValue: U;
|
||||
let wrapped: boolean;
|
||||
@@ -146,10 +124,34 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
this.get = function (): U {
|
||||
this.get = function (this: T): U {
|
||||
return key in this ? this[key] : defaultValue;
|
||||
}
|
||||
|
||||
this.nativeValueChange = function (owner: T, value: U): void {
|
||||
const currentValue = key in owner ? owner[key] : defaultValue;
|
||||
const changed = equalityComparer ? !equalityComparer(currentValue, value) : currentValue !== value;
|
||||
if (changed) {
|
||||
owner[key] = value;
|
||||
if (valueChanged) {
|
||||
valueChanged(owner, currentValue, value);
|
||||
}
|
||||
|
||||
if (owner.hasListeners(eventName)) {
|
||||
owner.notify({
|
||||
eventName: eventName,
|
||||
propertyName: name,
|
||||
object: owner,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
|
||||
if (affectsLayout) {
|
||||
owner.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
symbolPropertyMap[key] = this;
|
||||
}
|
||||
|
||||
@@ -162,13 +164,14 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescriptor {
|
||||
export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescriptor, definitions.CoercibleProperty<T, U> {
|
||||
private registered: boolean;
|
||||
private readonly name: string;
|
||||
public readonly key: symbol;
|
||||
public readonly native: symbol;
|
||||
public readonly defaultValueKey: symbol;
|
||||
public readonly defaultValue: U;
|
||||
public readonly nativeValueChange: (owner: T, value: U) => void;
|
||||
|
||||
public readonly get: () => U;
|
||||
public readonly set: (value: U) => void;
|
||||
@@ -177,7 +180,7 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
|
||||
|
||||
public readonly coerce: (target: T) => void;
|
||||
|
||||
constructor(options: CoerciblePropertyOptions<T, U>) {
|
||||
constructor(options: definitions.CoerciblePropertyOptions<T, U>) {
|
||||
const name = options.name;
|
||||
this.name = name;
|
||||
|
||||
@@ -272,6 +275,31 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
|
||||
return key in this ? this[key] : defaultValue;
|
||||
}
|
||||
|
||||
this.nativeValueChange = function (owner: T, value: U): void {
|
||||
const currentValue = key in owner ? owner[key] : defaultValue;
|
||||
const changed = equalityComparer ? !equalityComparer(currentValue, value) : currentValue !== value;
|
||||
if (changed) {
|
||||
owner[key] = value;
|
||||
owner[coerceKey] = value;
|
||||
if (valueChanged) {
|
||||
valueChanged(owner, currentValue, value);
|
||||
}
|
||||
|
||||
if (owner.hasListeners(eventName)) {
|
||||
owner.notify({
|
||||
eventName: eventName,
|
||||
propertyName: name,
|
||||
object: owner,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
|
||||
if (affectsLayout) {
|
||||
owner.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
symbolPropertyMap[key] = this;
|
||||
}
|
||||
|
||||
@@ -284,11 +312,11 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
|
||||
}
|
||||
}
|
||||
|
||||
export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> {
|
||||
export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> implements definitions.InheritedProperty<T, U> {
|
||||
public readonly sourceKey: symbol;
|
||||
public readonly setInheritedValue: (value: U) => void;
|
||||
|
||||
constructor(options: PropertyOptions<T, U>) {
|
||||
constructor(options: definitions.PropertyOptions<T, U>) {
|
||||
super(options);
|
||||
const name = options.name;
|
||||
const key = this.key;
|
||||
@@ -369,7 +397,7 @@ export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
export class CssProperty<T extends Style, U> {
|
||||
export class CssProperty<T extends Style, U> implements definitions.CssProperty<T, U> {
|
||||
private registered: boolean;
|
||||
|
||||
public readonly name: string;
|
||||
@@ -384,7 +412,7 @@ export class CssProperty<T extends Style, U> {
|
||||
public readonly defaultValueKey: symbol;
|
||||
public readonly defaultValue: U;
|
||||
|
||||
constructor(options: CssPropertyOptions<T, U>) {
|
||||
constructor(options: definitions.CssPropertyOptions<T, U>) {
|
||||
const name = options.name;
|
||||
this.name = name;
|
||||
|
||||
@@ -559,10 +587,10 @@ export class CssProperty<T extends Style, U> {
|
||||
}
|
||||
}
|
||||
|
||||
export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U> {
|
||||
export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U> implements definitions.InheritedCssProperty<T,U> {
|
||||
public setInheritedValue: (value: U) => void;
|
||||
|
||||
constructor(options: CssPropertyOptions<T, U>) {
|
||||
constructor(options: definitions.CssPropertyOptions<T, U>) {
|
||||
super(options);
|
||||
const name = options.name;
|
||||
|
||||
@@ -684,7 +712,7 @@ export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U>
|
||||
}
|
||||
}
|
||||
|
||||
export class ShorthandProperty<T extends Style, P> {
|
||||
export class ShorthandProperty<T extends Style, P> implements definitions.ShorthandProperty<T, P> {
|
||||
private registered: boolean;
|
||||
|
||||
public readonly key: symbol;
|
||||
@@ -697,7 +725,7 @@ export class ShorthandProperty<T extends Style, P> {
|
||||
public readonly native: symbol;
|
||||
public readonly sourceKey: symbol;
|
||||
|
||||
constructor(options: ShorthandPropertyOptions<P>) {
|
||||
constructor(options: definitions.ShorthandPropertyOptions<P>) {
|
||||
const name = options.name;
|
||||
this.name = name;
|
||||
|
||||
@@ -712,7 +740,7 @@ export class ShorthandProperty<T extends Style, P> {
|
||||
|
||||
const converter = options.converter;
|
||||
|
||||
function setLocalValue(this: T, value: string| P): void {
|
||||
function setLocalValue(this: T, value: string | P): void {
|
||||
this[sourceKey] = ValueSource.Local;
|
||||
if (this[key] !== value) {
|
||||
this[key] = value;
|
||||
|
||||
@@ -374,20 +374,6 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
// public _setCore(data: PropertyChangeData) {
|
||||
// super._setCore(data);
|
||||
// this._updateTwoWayBinding(data.propertyName, data.value);
|
||||
// }
|
||||
|
||||
public nativePropertyChanged(property: Property<ViewBase, any>, newValue: any): void {
|
||||
if (this._updatingJSPropertiesDict[property.native]) {
|
||||
return;
|
||||
}
|
||||
this._updatingJSPropertiesDict[property.native] = true;
|
||||
property.set.call(this, newValue);
|
||||
delete this._updatingJSPropertiesDict[property.native];
|
||||
}
|
||||
|
||||
public requestLayout(): void {
|
||||
//
|
||||
}
|
||||
|
||||
6
tns-core-modules/ui/core/view.d.ts
vendored
6
tns-core-modules/ui/core/view.d.ts
vendored
@@ -543,14 +543,8 @@ declare module "ui/core/view" {
|
||||
public eachChildView(callback: (view: View) => boolean): void;
|
||||
|
||||
//@private
|
||||
/**
|
||||
* A property has changed on the native side directly - e.g. the user types in a TextField.
|
||||
*/
|
||||
public nativePropertyChanged(property: Property<any, any>, newValue: any): void;
|
||||
|
||||
isLayoutRequired: boolean;
|
||||
_gestureObservers: any;
|
||||
// _isInheritedChange(): boolean;
|
||||
|
||||
_updateLayout(): void;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user