如何上传照片 (ng2-file-upload) Angular cannot read 属性 'push' of undefined
How to upload photo (ng2-file-upload) Angular cannot read property 'push' of undefined
我正在尝试为 Recipe 上传新照片,效果不错。
照片正在上传,但我在控制台中遇到错误,要查看新照片,我必须刷新浏览器。
我使用 asp.net 核心作为模型和控制器,angular 作为视图
如何解决这个问题?
组件
import { Component, OnInit, ViewChild, Input } from '@angular/core';
import { Recipe } from 'src/app/_models/recipe';
import { ActivatedRoute } from '@angular/router';
import { RecipeService } from 'src/app/_services/recipe/recipe.service';
import { AuthService } from 'src/app/_services/auth.service';
import { AlertifyService } from 'src/app/_services/alertify.service';
import { NgForm } from '@angular/forms';
import { RecipePhoto } from 'src/app/_models/recipePhoto';
import { FileUploader } from 'ng2-file-upload';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-recipe-edit',
templateUrl: './recipe-edit.component.html',
styleUrls: ['./recipe-edit.component.css']
})
export class RecipeEditComponent implements OnInit {
@ViewChild('editForm', {static: true}) editForm: NgForm;
recipe: Recipe;
photos: RecipePhoto[];
uploader: FileUploader;
hasBaseDropZoneOver = false;
baseUrl = environment.apiUrl;
currentMain: RecipePhoto;
constructor(private route: ActivatedRoute, private recipeService: RecipeService, private authService: AuthService,
private alertify: AlertifyService) { }
ngOnInit() {
this.route.data.subscribe(data => {
this.recipe = data.recipe;
});
this.initializeUploader();
}
public fileOverBase(e: any): void {
this.hasBaseDropZoneOver = e;
}
initializeUploader() {
this.uploader = new FileUploader({
url: this.baseUrl + 'users/' + this.authService.decodedToken.nameid + '/recipes/' + this.recipe.id + '/photos',
authToken: 'Bearer ' + localStorage.getItem('token'),
isHTML5: true,
allowedFileType: ['image'],
removeAfterUpload: true,
autoUpload: false,
maxFileSize: 10 * 1024 * 1024
});
this.uploader.onAfterAddingFile = (file) => {file.withCredentials = false; };
this.uploader.onSuccessItem = (item, response, status, headers) => {
if (response) {
const res: RecipePhoto = JSON.parse(response);
const photo = {
id: res.id,
url: res.url,
dateAdded: res.dateAdded,
description: res.description,
isMain: res.isMain
};
this.photos.push(photo);
if (photo.isMain) {
this.recipeService.changeRecipePhoto(photo.url);
this.recipeService.currentRecipe.photoUrl = photo.url;
this.recipe = this.recipeService.currentRecipe;
}
}
};
}
}
Html
<div class="container">
<div class="row">
<div class="col-sm-2" *ngFor="let photo of recipe.recipePhotos">
<img src="{{photo.url}}" class="img-thumbnail p-1" alt="">
<div class="text-center">
<button type="button" class="btn btn-sm btn-danger"
(click)="deletePhoto(photo.id)" >
<i class="fa fa-trash-o"></i></button>
</div>
</div>
</div>
<form #editForm="ngForm" id="editForm" (ngSubmit)="updateRecipe(recipe.id)" >
<h5 class=" text-center mt-4">Description</h5>
<textarea name="description" cols=100% rows="6" class="form-contorl mt-2"
[(ngModel)]="recipe.description"></textarea>
<h5 class=" text-center mt-2">Location Details:</h5>
<div class="form-group mt-3">
<label for="city">Name</label>
<input class="form-control" type="text" name="name" [(ngModel)]="recipe.name">
</div>
<div class="form-group">
<label for="country">Ingredients</label>
<input class="form-control" type="text" name="country" [(ngModel)]="recipe.ingredients">
</div>
</form>
<button [disabled]="!editForm.dirty" form="editForm" class="btn btn-success btn-block">Save changes</button>
</div>
<div class="containter">
<div class="row mt-3">
<div class="col-md-3 mt-3">
<h3>Add Photos</h3>
<div ng2FileDrop
[ngClass]="{'nv-file-over': hasBaseDropZoneOver}"
(fileOver)="fileOverBase($event)"
[uploader]="uploader"
class="card bg-faded p-3 text-center mt-3 mb-3 my-drop-zone">
<i class="fa fa-upload fa-3x"></i>
Drop Photos Here
</div>
Multiple
<input type="file" ng2FileSelect [uploader]="uploader" multiple /><br/>
Single
<input type="file" ng2FileSelect [uploader]="uploader" />
</div>
<div class="col-md-6 ml-5" style="margin-bottom: 40px" *ngIf="uploader?.queue?.length">
<h3>Upload queue</h3>
<p>Queue length: {{ uploader?.queue?.length }}</p>
<table class="table">
<thead>
<tr>
<th width="50%">Name</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of uploader.queue">
<td><strong>{{ item?.file?.name }}</strong></td>
<td *ngIf="uploader.options.isHTML5" nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td>
<td *ngIf="uploader.options.isHTML5">
</tr>
</tbody>
</table>
<div>
<div>
Queue progress:
<div class="progress mb-4" >
<div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': uploader.progress + '%' }"></div>
</div>
</div>
<button type="button" class="btn btn-success btn-s"
(click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">
<span class="fa fa-upload"></span> Upload
</button>
<button type="button" class="btn btn-warning btn-s"
(click)="uploader.cancelAll()" [disabled]="!uploader.isUploading">
<span class="fa fa-ban"></span> Cancel
</button>
<button type="button" class="btn btn-danger btn-s"
(click)="uploader.clearQueue()" [disabled]="!uploader.queue.length">
<span class="fa fa-trash"></span> Remove
</button>
</div>
</div>
</div>
</div>
如果上传正常,为什么我会收到此错误
初始化照片变量:
photos: RecipePhoto[] = [];
为了在上传新照片后显示您的照片,您必须将照片变量添加到食谱变量中,因为您只在 ngOnInit
方法上初始化食谱变量。
ngOnInit() {
this.route.data.subscribe(data => {
// you're initializing your recipe variable here
// that's the reason why you can see your photos only on refreshing
this.recipe = data.recipe;
});
this.initializeUploader();
}
因为您在 HTML 代码中循环 recipe.recipePhotos。
<div class="col-sm-2" *ngFor="let photo of recipe.recipePhotos"> <!--<- here -->
您必须将新照片添加到 recipe.recipePhotos
变量,而不是仅推送到照片中。
this.uploader.onSuccessItem = (item, response, status, headers) => {
if (response) {
const res: RecipePhoto = JSON.parse(response);
const photo = {
id: res.id,
url: res.url,
dateAdded: res.dateAdded,
description: res.description,
isMain: res.isMain
};
// here you have your photos array after uploading a photo
// whit the new photo uploaded
this.photos.push(photo);
// but actually you're looping in your HTML the recipe.recipePhotos
// so you need to push the new photo into recipePhotos this way
this.recipe.recipePhotos.push(photo);
if (photo.isMain) {
this.recipeService.changeRecipePhoto(photo.url);
this.recipeService.currentRecipe.photoUrl = photo.url;
this.recipe = this.recipeService.currentRecipe;
}
}
我正在尝试为 Recipe 上传新照片,效果不错。 照片正在上传,但我在控制台中遇到错误,要查看新照片,我必须刷新浏览器。 我使用 asp.net 核心作为模型和控制器,angular 作为视图 如何解决这个问题?
组件
import { Component, OnInit, ViewChild, Input } from '@angular/core';
import { Recipe } from 'src/app/_models/recipe';
import { ActivatedRoute } from '@angular/router';
import { RecipeService } from 'src/app/_services/recipe/recipe.service';
import { AuthService } from 'src/app/_services/auth.service';
import { AlertifyService } from 'src/app/_services/alertify.service';
import { NgForm } from '@angular/forms';
import { RecipePhoto } from 'src/app/_models/recipePhoto';
import { FileUploader } from 'ng2-file-upload';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-recipe-edit',
templateUrl: './recipe-edit.component.html',
styleUrls: ['./recipe-edit.component.css']
})
export class RecipeEditComponent implements OnInit {
@ViewChild('editForm', {static: true}) editForm: NgForm;
recipe: Recipe;
photos: RecipePhoto[];
uploader: FileUploader;
hasBaseDropZoneOver = false;
baseUrl = environment.apiUrl;
currentMain: RecipePhoto;
constructor(private route: ActivatedRoute, private recipeService: RecipeService, private authService: AuthService,
private alertify: AlertifyService) { }
ngOnInit() {
this.route.data.subscribe(data => {
this.recipe = data.recipe;
});
this.initializeUploader();
}
public fileOverBase(e: any): void {
this.hasBaseDropZoneOver = e;
}
initializeUploader() {
this.uploader = new FileUploader({
url: this.baseUrl + 'users/' + this.authService.decodedToken.nameid + '/recipes/' + this.recipe.id + '/photos',
authToken: 'Bearer ' + localStorage.getItem('token'),
isHTML5: true,
allowedFileType: ['image'],
removeAfterUpload: true,
autoUpload: false,
maxFileSize: 10 * 1024 * 1024
});
this.uploader.onAfterAddingFile = (file) => {file.withCredentials = false; };
this.uploader.onSuccessItem = (item, response, status, headers) => {
if (response) {
const res: RecipePhoto = JSON.parse(response);
const photo = {
id: res.id,
url: res.url,
dateAdded: res.dateAdded,
description: res.description,
isMain: res.isMain
};
this.photos.push(photo);
if (photo.isMain) {
this.recipeService.changeRecipePhoto(photo.url);
this.recipeService.currentRecipe.photoUrl = photo.url;
this.recipe = this.recipeService.currentRecipe;
}
}
};
}
}
Html
<div class="container">
<div class="row">
<div class="col-sm-2" *ngFor="let photo of recipe.recipePhotos">
<img src="{{photo.url}}" class="img-thumbnail p-1" alt="">
<div class="text-center">
<button type="button" class="btn btn-sm btn-danger"
(click)="deletePhoto(photo.id)" >
<i class="fa fa-trash-o"></i></button>
</div>
</div>
</div>
<form #editForm="ngForm" id="editForm" (ngSubmit)="updateRecipe(recipe.id)" >
<h5 class=" text-center mt-4">Description</h5>
<textarea name="description" cols=100% rows="6" class="form-contorl mt-2"
[(ngModel)]="recipe.description"></textarea>
<h5 class=" text-center mt-2">Location Details:</h5>
<div class="form-group mt-3">
<label for="city">Name</label>
<input class="form-control" type="text" name="name" [(ngModel)]="recipe.name">
</div>
<div class="form-group">
<label for="country">Ingredients</label>
<input class="form-control" type="text" name="country" [(ngModel)]="recipe.ingredients">
</div>
</form>
<button [disabled]="!editForm.dirty" form="editForm" class="btn btn-success btn-block">Save changes</button>
</div>
<div class="containter">
<div class="row mt-3">
<div class="col-md-3 mt-3">
<h3>Add Photos</h3>
<div ng2FileDrop
[ngClass]="{'nv-file-over': hasBaseDropZoneOver}"
(fileOver)="fileOverBase($event)"
[uploader]="uploader"
class="card bg-faded p-3 text-center mt-3 mb-3 my-drop-zone">
<i class="fa fa-upload fa-3x"></i>
Drop Photos Here
</div>
Multiple
<input type="file" ng2FileSelect [uploader]="uploader" multiple /><br/>
Single
<input type="file" ng2FileSelect [uploader]="uploader" />
</div>
<div class="col-md-6 ml-5" style="margin-bottom: 40px" *ngIf="uploader?.queue?.length">
<h3>Upload queue</h3>
<p>Queue length: {{ uploader?.queue?.length }}</p>
<table class="table">
<thead>
<tr>
<th width="50%">Name</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of uploader.queue">
<td><strong>{{ item?.file?.name }}</strong></td>
<td *ngIf="uploader.options.isHTML5" nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td>
<td *ngIf="uploader.options.isHTML5">
</tr>
</tbody>
</table>
<div>
<div>
Queue progress:
<div class="progress mb-4" >
<div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': uploader.progress + '%' }"></div>
</div>
</div>
<button type="button" class="btn btn-success btn-s"
(click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">
<span class="fa fa-upload"></span> Upload
</button>
<button type="button" class="btn btn-warning btn-s"
(click)="uploader.cancelAll()" [disabled]="!uploader.isUploading">
<span class="fa fa-ban"></span> Cancel
</button>
<button type="button" class="btn btn-danger btn-s"
(click)="uploader.clearQueue()" [disabled]="!uploader.queue.length">
<span class="fa fa-trash"></span> Remove
</button>
</div>
</div>
</div>
</div>
如果上传正常,为什么我会收到此错误
初始化照片变量:
photos: RecipePhoto[] = [];
为了在上传新照片后显示您的照片,您必须将照片变量添加到食谱变量中,因为您只在 ngOnInit
方法上初始化食谱变量。
ngOnInit() {
this.route.data.subscribe(data => {
// you're initializing your recipe variable here
// that's the reason why you can see your photos only on refreshing
this.recipe = data.recipe;
});
this.initializeUploader();
}
因为您在 HTML 代码中循环 recipe.recipePhotos。
<div class="col-sm-2" *ngFor="let photo of recipe.recipePhotos"> <!--<- here -->
您必须将新照片添加到 recipe.recipePhotos
变量,而不是仅推送到照片中。
this.uploader.onSuccessItem = (item, response, status, headers) => {
if (response) {
const res: RecipePhoto = JSON.parse(response);
const photo = {
id: res.id,
url: res.url,
dateAdded: res.dateAdded,
description: res.description,
isMain: res.isMain
};
// here you have your photos array after uploading a photo
// whit the new photo uploaded
this.photos.push(photo);
// but actually you're looping in your HTML the recipe.recipePhotos
// so you need to push the new photo into recipePhotos this way
this.recipe.recipePhotos.push(photo);
if (photo.isMain) {
this.recipeService.changeRecipePhoto(photo.url);
this.recipeService.currentRecipe.photoUrl = photo.url;
this.recipe = this.recipeService.currentRecipe;
}
}