在我的应用程序中,ngOnInit()
加载货币,类别和制造商。我为此使用Angular 7反应形式。数据按预期加载,并在下拉菜单中填充值和第一个选项,并显示给用户。因此,这里的问题是,在完成表单并单击提交(使用默认下拉值)后,我看到category
,currency
和manufacturer
的空对象。
ProductNewComponent.ts
import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {ProductService} from '../service/product.service';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {CATEGORY_API_URL, CURRENCY_API_URL, MANUFACTURER_API_URL, PRODUCT_API_URL, SERVER_URL} from '../../../app.constants';
import {Product} from '../model/product';
import {Price} from '../model/price';
import {CategoryService} from '../../category/service/category.service';
import {Category} from '../../category/model/category';
import {Currency} from '../model/currency';
import {Manufacturer} from '../model/manufacturer';
@Component({
selector: 'app-product-new',
templateUrl: './product-new.component.html',
styleUrls: ['./product-new.component.css']
})
export class ProductNewComponent implements OnInit
{
categories: Array<Category>;
currencies: Array<Currency>;
manufacturers: Array<Manufacturer>;
productForm = new FormGroup({
id: new FormControl({value:'',disabled:true}, Validators.minLength(2)),
name: new FormControl(''),
description: new FormControl(''),
price: new FormControl(''),
amount: new FormControl(''),
categoryControl: new FormControl(''),
currencyControl: new FormControl( '' ),
manufacturerControl: new FormControl( '' ),
});
constructor(private productService:ProductService, private categoryService:CategoryService,private router:Router) {}
ngOnInit()
{
this.loadCategories();
this.loadCurrencies();
this.loadManufacturers();
}
createProduct()
{
const product=new Product();
product.name=this.productForm.value.name;
product.description=this.productForm.value.description;
product.price=new Price(this.productForm.value.currencyControl, this.productForm.value.price);
product.category=this.productForm.value.categoryControl;
product.manufacturer=this.productForm.value.manufacturerControl;
product.createdBy='Admin';
product.createdDate='';
product.lastModifiedBy='Admin';
product.lastModifiedDate='Admin';
const url=SERVER_URL+PRODUCT_API_URL+'create';
this.productService.createProduct(url,product).subscribe(
value =>
{
console.log('Successfully created product');
},error1 =>
{
console.log('Failed to create product');
},
()=>{
this.router.navigate(['/product/list']);
});
}
private loadCategories()
{
const url=SERVER_URL+CATEGORY_API_URL+'list';
this.categoryService.getCategories(url).subscribe(
categories =>
{
this.categories=categories;
},
error1 =>
{
},
()=>{
});
}
private loadCurrencies()
{
const url=SERVER_URL+CURRENCY_API_URL+'list';
this.productService.getCurrencies( url ).subscribe(
currencies =>
{
this.currencies=currencies;
},
error1 =>
{
},
() =>
{
} );
}
private loadManufacturers()
{
const url=SERVER_URL+MANUFACTURER_API_URL+'list';
this.productService.getManufacturers( url ).subscribe(
manufacturers =>
{
this.manufacturers=manufacturers;
},
error1 =>
{
},
() =>
{
} );
}
manufacturersDataAvailable(): boolean
{
return this.manufacturers!==undefined;
}
categoriesDataAvailable(): boolean
{
return this.categories!==undefined;
}
currenciesDataAvailable(): boolean
{
return this.currencies!==undefined;
}
goBack() {
this.router.navigate(['/product']);
}
}
product.component.html
<div>
<h2>Create New Product</h2>
<br/>
<form [formGroup]="productForm">
<div class="form-group">
<label for="id">Product Id</label>
<input type="text" class="form-control" id="id" formControlName="id">
<small id="emailHelp" class="form-text text-muted">Automatically generated by system</small>
</div>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" formControlName="name" required placeholder="Enter Product Name">
</div>
<div class="form-group">
<label for="description">Description</label>
<input type="text" width="200" height="100" class="form-control" id="description" formControlName="description" required placeholder="Enter Product Description">
</div>
<div class="form-group">
<label for="currencyControl">Price</label> <br/>
<label>
<select class="form-control" formControlName="currencyControl" name="currencyControl" id="currencyControl">
<option *ngFor="let currency of currencies">
{{currency.name}}
</option>
</select>
</label>
<input formControlName="amount" id="amount" placeholder="Enter Product Price (in USD)" required
style="margin: 10px; padding: 5px" type="text">
</div>
<div class="form-group">
<label>Category:
<select class="form-control" name="categoryControl" formControlName="categoryControl">
<option *ngFor="let category of categories">
{{category.name}}
</option>
</select>
</label>
</div>
<div class="form-group">
<label>Manufacturer:
<select class="form-control" formControlName="manufacturerControl" name="manufacturerControl">
<option *ngFor="let manufacturer of manufacturers">
{{manufacturer.name}}
</option>
</select>
</label>
</div>
<button type="submit" class="btn btn-primary" (click)="createProduct()">Submit</button>
<button type="button" class="btn btn-primary" style="margin-left: 30px" (click)="goBack()">Cancel</button>
</form>
</div>
如果我将select语句更改为使用[ngValue]="category"
,并且当从服务器加载数据时,在下拉列表中没有看到默认值并抛出错误。任何适用的指令或选项元素
答案 0 :(得分:1)
我找到了解决方案。由于某些原因,通过patchValue()
方法应用更新时,Angular不会更新类别选项(类别对象)。基于this documentation,我实现了compareCategoryFn
和compareManufacturerFn
。这会将旧值与新值进行比较,并使用通过patchValue()
方法接收的新值更新下拉列表
product-edit.component.html
<div *ngIf="productDataAvailable()">
<h2>Update Product</h2>
<br/>
<form [formGroup]="productForm">
<div class="form-group">
<label for="id">Product Id</label>
<input class="form-control" formControlName="id" id="id" name="id"type="text">
<small class="form-text text-muted" id="emailHelp"></small>
</div>
<div class="form-group">
<label for="name">Name</label>
<input class="form-control" formControlName="name" id="name" type="text">
</div>
<div class="form-group">
<label for="description">Description</label>
<input type="text" class="form-control" formControlName="description" id="description" required>
</div>
<div class="form-group">
<label for="amount">Price (In $)</label> <br/>
<input type="text" formControlName="amount" id="amount" required >
</div>
<div class="form-group">
<label>Category:
<select [compareWith]="compareCategoryFn" class="form-control"formControlName="categoryControl" name="categoryControl">
<option *ngFor="let category of categories" [ngValue]="category">
{{category.name}}
</option>
</select>
</label>
</div>
<div class="form-group">
<label>Manufacturer:
<select [compareWith]="compareManufacturerFn" class="form-control" formControlName="manufacturerControl" name="manufacturerControl">
<option *ngFor="let manufacturer of manufacturers" [ngValue]="manufacturer">
{{manufacturer.name}}
</option>
</select>
</label>
</div>
<button (click)="updateProduct()" class="btn btn-primary" type="submit">Update</button>
<button (click)="goBack()" class="btn btn-primary" style="margin-left: 30px" type="button">Cancel</button>
</form>
</div>
product-edit.component.ts
import {Component, OnInit} from '@angular/core';
import {Product} from '../model/product';
import {ProductService} from '../service/product.service';
import {ActivatedRoute, Router} from '@angular/router';
import {CATEGORY_API_URL, CURRENCY_API_URL, MANUFACTURER_API_URL, PRODUCT_API_URL, SERVER_URL} from '../../../app.constants';
import {FormControl, FormGroup} from '@angular/forms';
import {Currency} from '../model/currency';
import {Category} from '../../category/model/category';
import {Manufacturer} from '../../manufacturer/model/manufacturer';
import {CategoryService} from '../../category/service/category.service';
@Component( {
selector: 'app-product-edit',
templateUrl: './product-edit.component.html',
styleUrls: ['./product-edit.component.css']
} )
export class ProductEditComponent implements OnInit
{
product: Product;
categories: Array<Category>;
currencies: Array<Currency>;
manufacturers: Array<Manufacturer>;
productForm=new FormGroup(
{
id: new FormControl( {value: '', disabled: true} ),
name: new FormControl( '' ),
description: new FormControl( '' ),
price: new FormControl( '' ),
amount: new FormControl( '' ),
categoryControl: new FormControl(null ),
currency: new FormControl( '' ),
manufacturerControl: new FormControl( null )
} );
constructor(private productService: ProductService,
private categoryService: CategoryService,
private route: ActivatedRoute,
private router: Router)
{
}
ngOnInit()
{
this.loadCategories();
this.loadCurrencies();
this.loadManufacturers();
this.getProduct();
}
private getProduct()
{
const id=this.route.snapshot.paramMap.get( 'id' );
const url=SERVER_URL+PRODUCT_API_URL+'find/'+id;
this.productService.getProductDetails( url ).pipe()
.subscribe(
data =>
{
this.product=data;
this.productForm.patchValue(
{
id: data.id,
name: data.name,
description: data.description,
price: data.price,
amount: data.price.amount,
currency: data.price.currency,
categoryControl: data.category,
manufacturerControl: data.manufacturer,
});
},
error =>
{
console.log( error );
},
() => console.log( 'getProduct() success' ) );
}
private updateProduct()
{
const id=this.route.snapshot.paramMap.get( 'id' );
const url=SERVER_URL+PRODUCT_API_URL+'update';
const product = new Product();
product.id=Number( id );
product.name=this.productForm.value.name;
product.description=this.productForm.value.description;
product.category=this.productForm.value.categoryControl;
product.manufacturer=this.productForm.value.manufacturerControl;
product.price=this.productForm.value.price;
product.price.amount=this.productForm.value.amount;
product.lastModifiedBy='Admin';
product.lastModifiedDate='Admin';
this.productService.updateProduct( url, product ).subscribe(
value =>
{
console.log( 'Successfully updated product' );
}, error1 =>
{
console.log( 'Failed to update product' );
},
() =>
{
this.router.navigate( ['/product/list'] );
} );
}
private loadCategories()
{
const url=SERVER_URL+CATEGORY_API_URL+'list';
this.categoryService.getCategories( url ).subscribe(
categories =>
{
this.categories=categories;
console.log( 'Successfully loaded categories' );
},
error1 =>
{
console.log( 'Failed to load categories' );
},
() =>
{
} );
}
private loadCurrencies()
{
const url=SERVER_URL+CURRENCY_API_URL+'list';
this.productService.getCurrencies( url ).subscribe(
currencies =>
{
this.currencies=currencies;
},
error1 =>
{
console.log( 'Failed to load currencies' );
},
() =>
{
} );
}
private loadManufacturers()
{
const url=SERVER_URL+MANUFACTURER_API_URL+'list';
this.productService.getManufacturers( url ).subscribe(
manufacturers =>
{
this.manufacturers=manufacturers;
console.log( 'Successfully loaded manufacturers' );
},
error1 =>
{
console.log( 'Failed to load manufacturers' );
},
() =>
{
} );
}
productDataAvailable(): boolean
{
return this.product!==undefined;
}
compareCategoryFn(c1: Category, c2: Category): boolean
{
return c1 && c2 ? c1.id === c2.id : c1 === c2;
}
compareManufacturerFn(c1: Manufacturer, c2: Manufacturer): boolean
{
return c1 && c2 ? c1.id === c2.id : c1 === c2;
}
goBack()
{
this.router.navigate( ['/product/list'] );
}
}
答案 1 :(得分:0)
我认为这是Angular 4 - Select default value in dropdown [Reactive Forms]的副本
问题是您在以下位置将默认值设置为''
: categoryControl: new FormControl(''),
currencyControl: new FormControl( '' ),
manufacturerControl: new FormControl( '' ),