Skip to content

Commit dad72c1

Browse files
authored
Merge pull request #576 from NativeScript/hdeshev/reactive-forms
Reactive forms support
2 parents a68649d + d587380 commit dad72c1

12 files changed

+57
-18
lines changed

Diff for: nativescript-angular/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ export * from "./view-util";
1717
export * from "./animation-driver";
1818
export * from "./resource-loader";
1919
export * from "./element-registry";
20+
export * from "./value-accessors/base-value-accessor";

Diff for: nativescript-angular/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"devDependencies": {
4545
"tns-core-modules": ">=2.5.0 || >=2.5.0-2016",
4646
"zone.js": "^0.6.21",
47-
"typescript": "^2.0.2",
47+
"typescript": "~2.0.10",
4848
"tslint": "~4.0.1",
4949
"codelyzer": "^2.0.0-beta.1",
5050
"@angular/compiler-cli": "~2.2.1",

Diff for: nativescript-angular/value-accessors/base-value-accessor.ts

+17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
import { ControlValueAccessor } from "@angular/forms";
22

3+
export function generateValueAccessorSelector(...tagNames: string[]): string {
4+
const tags: string[] = [];
5+
tagNames.forEach(tagName => {
6+
tags.push(tagName); // regular tag
7+
tags.push(tagName.charAt(0).toLowerCase() + tagName.slice(1)); // lowercase first char
8+
tags.push(tagName.split(/(?=[A-Z])/).join("-").toLowerCase()); // kebab case
9+
});
10+
11+
const selectors = [];
12+
for (const tag of tags) {
13+
for (const directive of ["ngModel", "formControlName"]) {
14+
selectors.push(`${tag}[${directive}]`);
15+
}
16+
}
17+
return selectors.join(", ");
18+
}
19+
320
export class BaseValueAccessor<TView> implements ControlValueAccessor {
421
constructor(public view: TView) { }
522

Diff for: nativescript-angular/value-accessors/checked-value-accessor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core";
22
import { NG_VALUE_ACCESSOR } from "@angular/forms";
33
import { isBlank } from "../lang-facade";
4-
import { BaseValueAccessor } from "./base-value-accessor";
4+
import { BaseValueAccessor, generateValueAccessorSelector } from "./base-value-accessor";
55
import { Switch } from "ui/switch";
66

77
const CHECKED_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
@@ -17,7 +17,7 @@ const CHECKED_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
1717
* ```
1818
*/
1919
@Directive({
20-
selector: "Switch[ngModel], switch[ngModel]", // tslint:disable-line:directive-selector
20+
selector: generateValueAccessorSelector("Switch"),
2121
providers: [CHECKED_VALUE_ACCESSOR]
2222
})
2323
export class CheckedValueAccessor extends BaseValueAccessor<Switch> { // tslint:disable-line:directive-class-suffix

Diff for: nativescript-angular/value-accessors/date-value-accessor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core";
22
import { NG_VALUE_ACCESSOR } from "@angular/forms";
33
import { isBlank, isDate } from "../lang-facade";
4-
import { BaseValueAccessor } from "./base-value-accessor";
4+
import { BaseValueAccessor, generateValueAccessorSelector } from "./base-value-accessor";
55
import { DatePicker } from "ui/date-picker";
66

77
const DATE_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
@@ -17,7 +17,7 @@ const DATE_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
1717
* ```
1818
*/
1919
@Directive({
20-
selector: "DatePicker[ngModel], datePicker[ngModel], date-picker[ngModel]", // tslint:disable-line:max-line-length directive-selector
20+
selector: generateValueAccessorSelector("DatePicker"),
2121
providers: [DATE_VALUE_ACCESSOR]
2222
})
2323
export class DateValueAccessor extends BaseValueAccessor<DatePicker> { // tslint:disable-line:directive-class-suffix

Diff for: nativescript-angular/value-accessors/number-value-accessor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core";
22
import { NG_VALUE_ACCESSOR } from "@angular/forms";
33
import { isBlank, isNumber } from "../lang-facade";
4-
import { BaseValueAccessor } from "./base-value-accessor";
4+
import { BaseValueAccessor, generateValueAccessorSelector } from "./base-value-accessor";
55
import { Slider } from "ui/slider";
66

77
const NUMBER_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
@@ -17,7 +17,7 @@ const NUMBER_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
1717
* ```
1818
*/
1919
@Directive({
20-
selector: "Slider[ngModel], slider[ngModel]", // tslint:disable-line:directive-selector
20+
selector: generateValueAccessorSelector("Slider"),
2121
providers: [NUMBER_VALUE_ACCESSOR]
2222
})
2323
export class NumberValueAccessor extends BaseValueAccessor<Slider> { // tslint:disable-line:directive-class-suffix

Diff for: nativescript-angular/value-accessors/selectedIndex-value-accessor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Directive, ElementRef, forwardRef, AfterViewInit, HostListener } from "@angular/core";
22
import { NG_VALUE_ACCESSOR } from "@angular/forms";
3-
import { BaseValueAccessor } from "./base-value-accessor";
3+
import { BaseValueAccessor, generateValueAccessorSelector } from "./base-value-accessor";
44
import { View } from "ui/core/view";
55
import { convertToInt } from "../common/utils";
66

@@ -19,7 +19,7 @@ export type SelectableView = {selectedIndex: number} & View;
1919
* ```
2020
*/
2121
@Directive({
22-
selector: "SegmentedBar[ngModel], segmentedBar[ngModel], segmented-bar[ngModel], ListPicker[ngModel], listPicker[ngModel], list-picker[ngModel], TabView[ngModel], tabView[ngModel], tab-view[ngModel]", // tslint:disable-line:max-line-length directive-selector
22+
selector: generateValueAccessorSelector("SegmentedBar", "ListPicker", "TabView"),
2323
providers: [SELECTED_INDEX_VALUE_ACCESSOR]
2424
})
2525
export class SelectedIndexValueAccessor extends BaseValueAccessor<SelectableView> implements AfterViewInit { // tslint:disable-line:max-line-length directive-class-suffix

Diff for: nativescript-angular/value-accessors/text-value-accessor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core";
22
import { NG_VALUE_ACCESSOR } from "@angular/forms";
33
import { isBlank } from "../lang-facade";
4-
import { BaseValueAccessor } from "./base-value-accessor";
4+
import { BaseValueAccessor, generateValueAccessorSelector } from "./base-value-accessor";
55
import { View } from "ui/core/view";
66

77
const TEXT_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
@@ -19,7 +19,7 @@ export type TextView = {text: string} & View;
1919
* ```
2020
*/
2121
@Directive({
22-
selector: "TextField[ngModel], textField[ngModel], text-field[ngModel], TextView[ngModel], textView[ngModel], text-view[ngModel], SearchBar[ngModel], search-bar[ngModel], searchBar[ngModel]", // tslint:disable-line:max-line-length directive-selector
22+
selector: generateValueAccessorSelector("TextField", "TextView", "SearchBar"),
2323
providers: [TEXT_VALUE_ACCESSOR]
2424
})
2525
export class TextValueAccessor extends BaseValueAccessor<TextView> { // tslint:disable-line:directive-class-suffix

Diff for: nativescript-angular/value-accessors/time-value-accessor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core";
22
import { NG_VALUE_ACCESSOR } from "@angular/forms";
33
import { isBlank, isDate } from "../lang-facade";
4-
import { BaseValueAccessor } from "./base-value-accessor";
4+
import { BaseValueAccessor, generateValueAccessorSelector } from "./base-value-accessor";
55
import { TimePicker } from "ui/time-picker";
66

77
const TIME_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
@@ -17,7 +17,7 @@ const TIME_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR,
1717
* ```
1818
*/
1919
@Directive({
20-
selector: "TimePicker[ngModel], timePicker[ngModel], time-picker[ngModel]", // tslint:disable-line:max-line-length directive-selector
20+
selector: generateValueAccessorSelector("TimePicker"),
2121
providers: [TIME_VALUE_ACCESSOR]
2222
})
2323
export class TimeValueAccessor extends BaseValueAccessor<TimePicker> { // tslint:disable-line:directive-class-suffix

Diff for: ng-sample/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"nativescript-dev-typescript": "^0.3.1",
4646
"nativescript-dev-webpack": "0.0.13",
4747
"shelljs": "^0.7.0",
48-
"typescript": "^2.0.2"
48+
"typescript": "~2.0.10"
4949
},
5050
"nativescript": {
5151
"id": "org.nativescript.ngsample",

Diff for: tests/app/tests/value-accessor-tests.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {TimePicker} from "ui/time-picker";
88
import {ListPicker} from "ui/list-picker";
99
import {TextField} from "ui/text-field";
1010
import {
11+
generateValueAccessorSelector,
1112
NumberValueAccessor,
1213
CheckedValueAccessor,
1314
DateValueAccessor,
@@ -100,7 +101,7 @@ describe("two-way binding via ng-model", () => {
100101

101102
it("converts strings to int selection", () => {
102103
const accessor = new TestSelectedIndexValueAccessor()
103-
104+
104105
accessor.writeValue(null);
105106
accessor.ngAfterViewInit();
106107
assert.strictEqual(0, accessor.view.selectedIndex, "default to 0 on empty")
@@ -143,6 +144,26 @@ describe("two-way binding via ng-model", () => {
143144
});
144145
})
145146

147+
describe("target selector registration", () => {
148+
it("supports uppercase(unchanged) camel tags", () => {
149+
assert.include(generateValueAccessorSelector("TextField"), "TextField[ngModel]");
150+
});
151+
it("supports lowercase camel tags", () => {
152+
assert.include(generateValueAccessorSelector("TextField"), "textField[ngModel]");
153+
});
154+
it("supports kebab case tags", () => {
155+
assert.include(generateValueAccessorSelector("TextField"), "text-field[ngModel]");
156+
});
157+
it("supports formControlName", () => {
158+
assert.include(generateValueAccessorSelector("TextField"), "TextField[formControlName]");
159+
});
160+
it("supports multiple tags", () => {
161+
const selector = generateValueAccessorSelector("TextField", "TextView");
162+
assert.include(selector, "TextField[ngModel]");
163+
assert.include(selector, "TextField[formControlName]");
164+
});
165+
});
166+
146167
function formatDate(date: Date) {
147168
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
148169
}

Diff for: tests/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"nativescript": {
33
"id": "org.nativescript.ngtests",
44
"tns-android": {
5-
"version": "2.4.0"
5+
"version": "2.4.1"
66
},
77
"tns-ios": {
88
"version": "2.4.0"
@@ -56,7 +56,7 @@
5656
"mocha": "^2.4.5",
5757
"nativescript-dev-appium": "0.0.14",
5858
"nativescript-dev-typescript": "^0.3.1",
59-
"typescript": "^2.0.2",
59+
"typescript": "~2.0.10",
6060
"socket.io": "1.4.8",
6161
"socket.io-client": "1.4.8",
6262
"wd": "0.4.0"
@@ -67,4 +67,4 @@
6767
"run-appium-android": "nativescript-dev-appium android",
6868
"appium-ios-simulator": "tns build ios && nativescript-dev-appium ios-simulator"
6969
}
70-
}
70+
}

0 commit comments

Comments
 (0)