Skip to content

Commit e93e577

Browse files
Merge pull request #3 from NativeScript/amiorkov/reactive-forms-value-fix
Fix issues when used in Angular reactive forms
2 parents 74cbb23 + 6493d15 commit e93e577

File tree

5 files changed

+94
-40
lines changed

5 files changed

+94
-40
lines changed

demo-angular/src/app/examples/reactive-forms/reactive-forms-example.component.css

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,10 @@
2222
margin-left: 100;
2323
}
2424

25-
.small-picture {
26-
height: 70;
27-
margin: 20;
28-
}
29-
3025
.yellow-grid {
3126
background-color: #F5C518;
3227
}
3328

34-
.result-label {
35-
background-color: gray;
36-
color: white;
37-
padding: 10;
38-
margin-right: 20;
39-
}
40-
4129
ListView.picker-field {
4230
background-color: green;
4331
margin-left: 20;
@@ -57,3 +45,7 @@ ActionBar.picker-field {
5745
font-size: 20;
5846
font-weight: bold;
5947
}
48+
49+
.submit-button {
50+
margin: 20;
51+
}

demo-angular/src/app/examples/reactive-forms/reactive-forms-example.component.html

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
</ActionBar>
44
<GridLayout rows="100, *" columns="*, *" [formGroup]="movieForm" class="yellow-grid">
55
<Label row="0" col="0" text="Pick a movie:" class="black-label label-center field-name-label"></Label>
6-
<PickerField row="0" col="1" formControlName="movie" [(ngModel)]="selectedMovie" hint="select a movie"
7-
padding="10" pickerTitle="Pick a movie" class="picker-field" modalClass="myModal" textField="name" [items]="pickerItems">
6+
<PickerField #picker row="0" col="1" formControlName="movie" hint="select a movie" padding="10" pickerTitle="Pick a movie"
7+
class="picker-field" modalClass="myModal" valueField="year" textField="name" [items]="pickerItems">
88
<ng-template let-item="item">
99
<GridLayout rows="auto, *" columns="*, auto" class="yellow-grid">
1010
<Label [text]="item.name" colSpan="2" class="black-label item-template-top-label"></Label>
@@ -14,13 +14,7 @@
1414
</ng-template>
1515
</PickerField>
1616

17-
<GridLayout row="1" col="0" colSpan="2" rows="auto, auto, auto, auto" columns="*, *" backgroundColor="white">
18-
<Label row="0" col="0" colSpan="2" text="Result" class="black-label field-name-label" marginTop="20"></Label>
19-
<Label row="1" col="0" text="ngModel.name: " class="black-label field-name-label"></Label>
20-
<Label row="1" col="1" [text]="selectedMovie.name"></Label>
21-
<Label row="2" col="0" text="ngModel.year: " class="black-label field-name-label"></Label>
22-
<Label row="2" col="1" [text]="selectedMovie.year" ></Label>
23-
<Label row="3" col="0" text="ngModel.imageUrl: " class="black-label field-name-label"></Label>
24-
<Image row="3" col="1" [src]="selectedMovie.imageUrl" class="small-picture"></Image>
17+
<GridLayout row="1" col="0" colSpan="2" rows="auto, *" backgroundColor="white">
18+
<Button class="submit-button" text="Submit form" (tap)="onSubmit()"></Button>
2519
</GridLayout>
2620
</GridLayout>>

demo-angular/src/app/examples/reactive-forms/reactive-forms-example.component.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { Component, OnInit } from "@angular/core";
2-
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
1+
import { Component, OnInit, ViewChild } from "@angular/core";
2+
import { FormBuilder, FormGroup, FormControl, Validators } from "@angular/forms";
33
import { RouterExtensions } from "nativescript-angular/router";
44
import { ObservableArray } from "tns-core-modules/data/observable-array/observable-array";
5+
import { PickerFieldComponent } from "nativescript-picker/angular";
56

67
@Component({
78
selector: "ns-reactive-forms-example",
@@ -11,6 +12,7 @@ import { ObservableArray } from "tns-core-modules/data/observable-array/observab
1112
})
1213
export class ReactiveFormsExampleComponent implements OnInit {
1314
public pickerItems: ObservableArray<Movie>;
15+
@ViewChild("picker") pickerComp: PickerFieldComponent;
1416

1517
constructor(private routerExtensions: RouterExtensions, private fb: FormBuilder) {
1618
this.pickerItems = new ObservableArray([
@@ -24,20 +26,31 @@ export class ReactiveFormsExampleComponent implements OnInit {
2426
new Movie("One Flew Over the Cuckoo's Nest", 9, 1975, "https://m.media-amazon.com/images/M/MV5BZjA0OWVhOTAtYWQxNi00YzNhLWI4ZjYtNjFjZTEyYjJlNDVlL2ltYWdlL2ltYWdlXkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_UX182_CR0,0,182,268_AL_.jpg"),
2527
new Movie(" Lawrence of Arabia", 10, 1962, "https://m.media-amazon.com/images/M/MV5BYWY5ZjhjNGYtZmI2Ny00ODM0LWFkNzgtZmI1YzA2N2MxMzA0XkEyXkFqcGdeQXVyNjUwNzk3NDc@._V1_UY268_CR2,0,182,268_AL_.jpg"),
2628
]);
27-
this.selectedMovie = this.pickerItems.getItem(0);
29+
30+
this.movieForm = new FormGroup({
31+
movie: new FormControl(this.pickerItems.getItem(0).year, Validators.required),
32+
});
2833
}
2934

3035
ngOnInit(): void { }
3136

32-
public movieForm: FormGroup = this.fb.group({
33-
movie: [undefined, Validators.required],
34-
});
35-
36-
public selectedMovie: Movie;
37+
public movieForm: FormGroup;
3738

38-
public goBack() {
39+
Í; public goBack() {
3940
this.routerExtensions.backToPreviousPage();
4041
}
42+
43+
public onSubmit() {
44+
let formMovieValue = this.movieForm.get("movie").value;
45+
let selectedValue = this.pickerComp.nativeElement.selectedValue;
46+
console.log("picker selected value: ", selectedValue);
47+
console.log("Forms 'movie' value: ", formMovieValue);
48+
alert({
49+
title: "Forms 'movie' value:",
50+
message: `Forms 'movie' value: ${formMovieValue}`,
51+
okButtonText: "OK"
52+
});
53+
}
4154
}
4255

4356
class Movie {

src/picker.common.ts

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,8 @@ export class PickerField extends TextField implements TemplatedItemsView {
159159
if (selectedIndex !== undefined) {
160160
let object = this.getDataItem(selectedIndex);
161161
this.selectedIndex = selectedIndex;
162-
let value = this.getValueFromField("valueField", this.valueField, object);
163-
this.selectedValue = value === undefined ? object : value;
164162

165-
let textValue = this.getValueFromField("textField", this.textField, object);
166-
textValue = textValue === undefined ? object : textValue;
167-
this.text = textValue;
163+
this._updateSelectedValue(object);
168164
}
169165

170166
this.disposeModalView();
@@ -415,9 +411,70 @@ export class PickerField extends TextField implements TemplatedItemsView {
415411
}
416412
}
417413

414+
private _updateSelectedValue(object: any) {
415+
let value = this.getValueFromField("selectedValue", this.valueField, object);
416+
this.selectedValue = value === undefined ? object : value;
417+
}
418+
419+
private updatePickerText(object: any) {
420+
let textValue = this.getValueFromField("text", this.textField, object);
421+
textValue = textValue === undefined ? object : textValue;
422+
this.text = textValue;
423+
}
424+
418425
protected onModalAnimatedChanged(oldValue: boolean, newValue: boolean) { }
419426

420-
protected onSelectedValueChanged(oldValue: any, newValue: any) { }
427+
protected onSelectedValueChanged(oldValue: any, newValue: any) {
428+
if (this.hasItem(newValue)) {
429+
this.updatePickerText(newValue);
430+
return;
431+
}
432+
433+
let dataItem = this.getObjectFromValue(this.valueField, newValue);
434+
if (dataItem) {
435+
this.updatePickerText(dataItem);
436+
} else {
437+
this.text = newValue;
438+
}
439+
}
440+
441+
private getObjectFromValue(propertyName: string, value: any) {
442+
if (!propertyName) {
443+
return undefined;
444+
}
445+
446+
if (this.items) {
447+
for (let i = 0; i < this.items.length; i++) {
448+
let item = this._getDataItem(i);
449+
if (item.hasOwnProperty(propertyName)) {
450+
let dataItemValue = item[propertyName];
451+
if (dataItemValue === value) {
452+
return item;
453+
}
454+
}
455+
}
456+
}
457+
458+
return undefined;
459+
}
460+
461+
private hasItem(object: any) {
462+
if (this.items) {
463+
for (let i = 0; i < this.items.length; i++) {
464+
let item = this._getDataItem(i);
465+
if (item === object) {
466+
return true;
467+
}
468+
}
469+
}
470+
471+
return false;
472+
}
473+
474+
private _getDataItem(index: number): any {
475+
let thisItems = <ItemsSource>this.items;
476+
return thisItems.getItem ? thisItems.getItem(index) : thisItems[index];
477+
}
421478

422479
protected onValueFieldChanged(oldValue: string, newValue: string) { }
423480

src/picker.d.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export class PickerField extends TextField implements TemplatedItemsView {
5555
public valueField: string;
5656

5757
/**
58-
* Gets the object selected from the list in the modal view.
58+
* Gets or sets the object selected from the list in the modal view.
5959
*/
6060
public selectedValue: any;
6161

@@ -86,8 +86,6 @@ export class PickerField extends TextField implements TemplatedItemsView {
8686

8787
refresh();
8888

89-
_openModalHandler(args): void;
90-
9189
/**
9290
* Identifies the {@link modalAnimated} dependency property.
9391
*/

0 commit comments

Comments
 (0)