ngual中的Angualr2- ngModel无法正常工作。模型正确更新,但视图中出现一些错误

时间:2017-04-30 07:40:30

标签: angular angular2-ngmodel

我正在开展一项使用Angular2创建旅行计划器的小任务。工作流程如下:用户将输入起点目的地以及中间停止点数。一旦用户提交“开始”按钮,就会出现计划表,用户可以输入中间停止点以及添加/删除停止点。不知怎的,我没有得到屏幕截图所示的所需输出。First Screen

2nd Screen

在添加新的停止点时,这就是我得到的...... My output on adding a new stop point

期望的输出.... Desired output

这就是Tripdetails对象的样子。查看对象和视图之间的区别。

console image

代码如下: 的 Trip.ts

export class Trip {
    startPoint:string;
    destination:string;
    stops:number;
}

TripDetails.ts

export class TripDetail {
    startPoint:string;
    destination:string;
}

app.component.ts

import { Component } from '@angular/core';
import { Trip } from './Trip';
import { TripDetail } from './TripDetails';

@Component({
  selector: 'my-app',
  moduleId: module.id,
  templateUrl: 'app.component.html'
})

export class AppComponent  { 
    trip: Trip = {
        startPoint : "",
        destination : "",
        stops : 0
    };
    tripDetails: TripDetail[];

    clicked(startPoint:string, destination:string, stops:string):void {
        let length = parseInt(stops);
            this.trip.startPoint = startPoint;
            this.trip.destination = destination;
            this.trip.stops = length;
            this.tripDetails = [];
        for (let i=0 ; i< length; i++) {
            let tripDetail :TripDetail={
                startPoint: "",
                destination: ""
            }
            if( i==0) {
                tripDetail.startPoint = this.trip.startPoint;
            }
            if( i== length-1) {
                tripDetail.destination = this.trip.destination;
            }
            this.tripDetails.push(tripDetail);
        }
    }

    syncData(index:number, locationType:string) {
        if(locationType == 'destinationLocation') {
            this.tripDetails[index + 1].startPoint = this.tripDetails[index].destination; 

        }
        else if (locationType == 'sourceLocation') {
            this.tripDetails[index - 1].destination = this.tripDetails[index].startPoint; 
        }
    }

    addStop(index:number):void {
        let stop:TripDetail={
            startPoint:"newStop",
            destination:"newStop"
        }
        this.tripDetails.splice(index,0,stop);
    }   

    removeStop(index:number):void{
        let destination = this.tripDetails[index].destination,
            arrlength = this.tripDetails.length;
        if(index==0){
            return;
        }
        else if( index== arrlength-1) {
            this.tripDetails[index-1].destination = this.tripDetails[index].destination;
            this.tripDetails.splice(index,1);
        }
        else{
            this.tripDetails.splice(index,1);
            this.tripDetails[index].destination= destination;   
        }
    }


}

app.component.html

<div class="container content">
    <div>
        <form>
            <label for="startPoint">From:</label>
            <input class="form-control" type="text" placeholder="Enter start point" name="startPoint" [(ngModel)] = "trip.startPoint" >

            <label for="destination">To:</label>
            <input class="form-control" type="text" name="destination" placeholder="Enter destiantion" id="destination" [(ngModel)]="trip.destination" >

            <label for="Stops">Stops:</label>
            <input class="form-control" type="text" placeholder="Enter number of stops"  name="stops" id="stops" [(ngModel)]="trip.stops"  >

            <div class="go-btn">
                <button class="btn btn-primary" (click)="clicked(trip.startPoint,trip.destination,trip.stops)">Go</button>
            </div>
            <div *ngIf = "trip.stops && trip.startPoint && trip.destination" class="trip-table  table-bordered">
                <table class="table table-stripped">
                    <thead class="thead">
                        <tr scope="row">
                        <th>FROM</th><th>TO</th>
                    </tr>
                    </thead>
                    <tr *ngFor= " let stops of tripDetails; let i=index; let first = first; let last= last; trackBy: index ">
                        <td>

                            <input type="text" class="form-control"  name="locationFrom-{{i}}" [(ngModel)]= "stops.startPoint"  (input)="syncData(i, 'sourceLocation')" >
                        </td>
                        <td>

                            <input type="text" class="form-control"  name="locationTo-{{i}}" [(ngModel)]= "stops.destination"  (input)="syncData(i, 'destinationLocation')" >
                        </td>
                        <td>
                            <button class="btn btn-primary" (click)="addStop(i)">+</button>
                        </td>
                        <td>
                            <button class="btn btn-primary" (click)="removeStop(i)" >-</button>
                        </td>
                    </tr>
                </table>                
            </div>
        </form>
    </div>
</div>  

app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ BrowserModule , FormsModule],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

1 个答案:

答案 0 :(得分:1)

使用trackBy跟踪索引绝对正确,你只是遇到了一些问题。如果没有要跟踪的唯一trackby索引(带有属性的变量,例如ngModel),则需要[(ngModel)]="myItem.myProperty",因此在处理原始数组时需要trackBy,例如<div *ngFor="let item of items"> <input [(ngModel)]="item" /> </div> 在下面的例子中将需要:

tripDetails

如果您尝试修改上面的输入字段,输入字段会在输入内容时立即失去焦点。

但你可能会说......

  

我的数组不是原始类型,我的数组ngModel包含可以使用唯一trackBy索引跟踪的对象吗?

是的,如果您使用表单,没有ngModel就没问题。

但是由于我们正在处理一个表单,Angular并不真正关心唯一的name,而是查看ngModel属性,这基本上意味着该字段突然没有出现。 t有一个唯一的trackBy跟索引。

因此请使用<tr *ngFor= "let stops of tripDetails; let i=index; trackBy:trackByFn">

trackByFn(index: number, stops: string) {
  return index;
}

和组件中的相应功能:

res.status(200 / 500).send()

这是

Demo