插入产品和上传文件分别工作,但在Angular 6中不能一起工作

时间:2018-07-30 15:45:47

标签: angular typescript angular6

我正在开发我的第一个CRUD测试应用程序。

我有一个表格,上面有典型的产品名称,价格...和一个用于上传产品的输入文件。

我为表单的change事件创建了一个事件处理程序方法。效果很好。

我创建了这个uploadFile()方法,效果很好。

upload-file-service.ts

import {Injectable, Input} from '@angular/core';
import {Http, Response, Headers, RequestOptions} from '@angular/http';
import {Router, ActivatedRoute,Params} from '@angular/router';

import {map} from 'rxjs/operators';
import {_GLOBAL} from './global.service';
import {Observable} from 'rxjs';
import {Producto} from '../models/Producto.model';


 @Injectable()

export class UploadFileService
{
    public url:string;
    public filesToUpload:Array<File>;

    constructor()
    {
        this.url=_GLOBAL.url;//this has the URL of the REST service
        this.filesToUpload=[];
    }


    uploadFile(url:string, params:Array<string>,filesToUpload:Array<File>)
    {
        return new Promise((resolve, reject)=>{

        var formData:any= new FormData();

        var asyncRequest=new XMLHttpRequest();

        for(var i=0; i<filesToUpload.length;++i)
        {
             formData.append('filesUploaded[]',filesToUpload[i],filesToUpload[i].name);
        }

        asyncRequest.onreadystatechange=function(){
            if(asyncRequest.readyState==4){
                if(asyncRequest.status==200){
                    resolve(JSON.parse(asyncRequest.response));
                }else{
                    reject(asyncRequest.response);
                }
            }
        }

        asyncRequest.open('POST',url,true);

        asyncRequest.send(formData);
   });
}



fileChangeEvent(ElementObjectReferenceWhichTriggersEvent:any)// in this case, the input type="file"
{
    this.filesToUpload=<Array<File>>ElementObjectReferenceWhichTriggersEvent.target.files;//captura los archivos mandados en el input

    console.log(ElementObjectReferenceWhichTriggersEvent.target);

    console.log(ElementObjectReferenceWhichTriggersEvent.target.files[0]);

    console.log(this.filesToUpload);

   // return this.filesToUpload;
}

}

还有这项服务

create-product.service.ts

在此方法上,我有一个createProduct()方法,该方法从上面的服务中调用uploadFile()方法,从HTTP服务中调用http.post()

问题是,两种方法都可以单独很好地工作,但不能一起工作。

我的意思是,当我在此服务上进行此操作时:

import {Injectable} from '@angular/core';
import {Http, Response, Headers, RequestOptions} from '@angular/http';
import {Router, ActivatedRoute,Params} from '@angular/router';

import {map} from 'rxjs/operators';
import {_GLOBAL} from './global.service';
import {Observable} from 'rxjs';
import {Producto} from '../models/Producto.model';
import {UploadFileService} from './upload-file.service';


@Injectable()

export class CreateProductService{

    public url:string;
    public errorMessage:string;
    public productToInsert:Producto;
    public imageData:string;

    constructor(
                    private _http:Http,
                    private _route:ActivatedRoute, 
                    private _router:Router,
                    private _uploadFile:UploadFileService
               )
    {


        this.url=_GLOBAL.url;
        this.errorMessage="";

        this.productToInsert=new Producto("","","","");

    }//end constructor


    ngOnInit()
    {


    }


    createProduct()
    {



        let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });

        let options = new RequestOptions({ headers: headers }


        this._uploadFile.uploadFile(`${this.url}/upload-file`,[],this._uploadFile.filesToUpload).then(

            (result)=>{
                console.log(result["complete_name"]);
            },
            (error)=>
            {
                console.log(error);
            }
        );

        //file is successfully uploaded, then I insert the product:

        this._http.post(`${this.url}/crear-producto`,this.productToInsert,options).pipe(
            map(

                   (res)=>{

                       console.log ("res del callback del map" + res);

                       return res.json();

                    },(err)=>{

                         return err;

                    }


                )



            ) .subscribe(

                (response)=>
                {
                    console.log(response);
                    this._router.navigate(['all-products']);


                },
                (error)=>
                {
                     console.log(error);

                }

            );



}

}

有效:文件已上传且产品已正确插入...问题是,在数据库上我希望将result["complete_name"]存储在image字段中,然后我可以在获得所有产品,而不是http.post()

包含在字段中的“ c:/fakepath/PICTURE.PNG”

为此,我需要捕获响应,然后使用result["complete_name"]

更改对象productToInsert.imagen

为此,我仅在promise响应成功时才使用http.post()。因此,在上传图像时,我捕获了响应结果,将其添加到post()方法中作为参数传递的对象中,然后发送它。

import {Injectable} from '@angular/core';
import {Http, Response, Headers, RequestOptions} from '@angular/http';
import {Router, ActivatedRoute,Params} from '@angular/router';

import {map} from 'rxjs/operators';
import {_GLOBAL} from './global.service';
import {Observable} from 'rxjs';
import {Producto} from '../models/Producto.model';
import {UploadFileService} from './upload-file.service';


@Injectable()

export class CreateProductService{

    public url:string;
    public errorMessage:string;
    public productToInsert:Producto;
    public imageData:string;

    constructor(
                    private _http:Http,
                    private _route:ActivatedRoute, 
                    private _router:Router,
                    private _uploadFile:UploadFileService
                )
    {


        this.url=_GLOBAL.url;
        this.errorMessage="";

        this.productToInsert=new Producto("","","","");

    }//end constructor


    ngOnInit()
    {


    }


    createProduct()
    {



        let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });

        let options = new RequestOptions({ headers: headers });

        this._uploadFile.uploadFile(`${this.url}/upload-file`,[],this._uploadFile.filesToUpload).then(

        (result)=>{
            console.log(result["complete_name"]);
            this.productToInsert.imagen=result["complete_name"];


            this._http.post(`${this.url}/crear-producto`,this.productToInsert,options).pipe(


                map(

                    (res)=>{
                               return res.json();

                    },(err)=>{

                               return err;

                    }


                )).subscribe(

                    (response)=>
                    {
                        console.log( response);
                        this._router.navigate(['all-products']);


                    },
                    (error)=>
                    {
                        console.log(+error);

                     }

                );

            },
            (error)=>{
                console.log(error);

            }

       );
   }

}

但这不起作用。我得到200的响应,但是在这种情况下,对象似乎是空的(在所有字段上为空),而不是来自表单的对象。

这是使用的表格

create-product-component.html

<form #formCreateProduct="ngForm" (ngSubmit)="_createProduct.createProduct();  formCreateProduct.reset()" class="col-lg-6" id="form-crear-producto-id">

    <div class="form-group">

        <label for="nombreLabel"> Name of the new product:

            <span *ngIf="!nombre.valid && nombre.touched && _createProduct.productToInsert.nombre.length != 0" class="label label-danger">Minimun 3 characters please</span>

        </label>  


       <input type="text" class="form-control" name="name" #nombre="ngModel" pattern =".{3,}"[(ngModel)]="_createProduct.productToInsert.nombre" required /> <br/>



    </div>

    <div class="form-group">

        <label for="priceLabel">Price ( € ): (please decimals with a dot. Ex:29.5)

            <span *ngIf="!precio.valid && precio.touched && _createProduct.productToInsert.precio.length != 0" class="label label-danger">Price is not valid. At least one number please, and only numbers</span>

       </label>

       <input type="text"  class="form-control" name="price" #precio="ngModel" pattern="[0-9.]+" [(ngModel)]="_createProduct.productToInsert.precio" required />  <br/>


    </div>


    <div class="form-group">

        <label for="imageLabel">Image:</label>

         <!--file doesnt suport the ngmodel-->
            <input type="file"  class="form-control" name="imagen" (change)="_uploadFile.fileChangeEvent($event)" [(ngModel)]="_createProduct.productToInsert.imagen" required /> <br/>

    </div>


    <div class="form-group">

        <label for="descriptionLabel">Description:</label>

        <div [ngClass]="{'TopLength': _createProduct.productToInsert.descripcion.length==300}">{{_createProduct.productToInsert.descripcion.length}}/300</div>

           <textarea name="description" class="form-control" maxlength="300" #descripcion="ngModel" [(ngModel)]="_createProduct.productToInsert.descripcion" cols="40" rows="3" ></textarea> <br/>


     </div>



     <input type="submit" value={{title}}  [disabled]="formCreateProduct.invalid" class ="btn btn-lg btn-success" /> <br/>

</form>

我知道,因为这是我的第一个带有角度服务的应用程序,所以使用这些东西可能有些奇怪,但是我尝试过:

  • 避免提供服务,并将其直接放在component.ts中。

  • 仅将服务用于create-component-service.ts,在其中放置所有方法(uploadFile,eventHandler,createProduct),然后在组件上使用它们(我想这实际上是使用服务的正确方法)

  • 绑定“ this”范围,以查看箭头功能内部的范围是否存在任何问题。

但是没有任何效果。我不知道为什么分别使用它们时可以访问并正确使用该对象和这两种方法,但是当一起使用这种方法时,我发现了这个问题,这是老师告诉我们要做的。

一个可能对您有用的提示是,我在某个地方出现了错误(除了大声笑),但我必须说这个错误,而其他错误则使我可以分别上传文件和创建产品,因此我没有问题,因此我计划以后再调试。

Uncaught (in promise): SecurityError: The operation is insecure. ./node_modules/@angular/platform-browser/fesm5/platform-browser.js/DefaultDomRenderer2.prototype.setProperty@http://localhost:4200/vendor.js:56793:9 ./node_modules/@angular/core/fesm5/core.js/DebugRenderer2.prototype.setProperty@http://localhost:4200/vendor.js:42592:9 ./node_modules/@angular/forms/fesm5/forms.js/DefaultValueAccessor.prototype.writeValue@http://localhost:4200/vendor.js:48231:9 setUpModelChangePipeline/<@http://localhost:4200/vendor.js:49205:9 ./node_modules/@angular/forms/fesm5/forms.js/FormControl.prototype.setValue/<@http://localhost:4200/vendor.js:50262:65 ./node_modules/@angular/forms/fesm5/forms.js/FormControl.prototype.setValue@http://localhost:4200/vendor.js:50262:13 ./node_modules/@angular/forms/fesm5/forms.js/NgModel.prototype._updateValue/<@http://localhost:4200/vendor.js:51617:46 ./node_modules/zone.js/dist/zone.js/</ZoneDelegate.prototype.invoke@http://localhost:4200/polyfills.js:2710:17 onInvoke@http://localhost:4200/vendor.js:35055:24 ./node_modules/zone.js/dist/zone.js/</ZoneDelegate.prototype.invoke@http://localhost:4200/polyfills.js:2709:17 ./node_modules/zone.js/dist/zone.js/</Zone.prototype.run@http://localhost:4200/polyfills.js:2460:24 scheduleResolveOrReject/<@http://localhost:4200/polyfills.js:3194:29 ./node_modules/zone.js/dist/zone.js/</ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.js:2743:17 onInvokeTask@http://localhost:4200/vendor.js:35046:24 ./node_modules/zone.js/dist/zone.js/</ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.js:2742:17 ./node_modules/zone.js/dist/zone.js/</Zone.prototype.runTask@http://localhost:4200/polyfills.js:2510:28 drainMicroTaskQueue@http://localhost:4200/polyfills.js:2917:25 ./node_modules/zone.js/dist/zone.js/</ZoneTask.invokeTask@http://localhost:4200/polyfills.js:2822:21 invokeTask@http://localhost:4200/polyfills.js:3862:9 globalZoneAwareCallback@http://localhost:4200/polyfills.js:3888:17

1 个答案:

答案 0 :(得分:0)

我解决了。这是一个愚蠢的事情:

在我的组件中,问题来自以前的版本,格式为:

<form #formCreateProduct="ngForm" (ngSubmit)="_createProduct.createProduct();formCreateProduct.reset()" class="col-lg-6" id="form-crear-producto-id">

在我实际发送表单值之前,reset()方法将所有表单值设置为null。删除了此方法(在新版本中,我进行了重定向,因此不需要它),并解决了问题。 2天的时间...:O