how to insert image in web API uaing observable

Hi,

I can insert data into the server via web API, but l have no idea how to insert picture as i have search for several hours about this but was not able to find any useful materials. For instance, I have EmployeeId, EmployeeName, PhotoOfEmployee,

How to insert Picture of each employee into the server using observables method?  Kindly assist


7 Replies

PS Pavithra Subramaniyam Syncfusion Team March 23, 2022 09:04 AM UTC

Hi Charles,  
You can achieve your requirement by using the “Dialog template” feature inside which you can render a File uploader component to insert, preview and save the image details. If you want to show the image in Grid view, then you can use the “Column Template” feature. Please refer to the below documentation for more information.  
  
  
Please get back to us if you need further assistance on this.  
Regards,  
Pavithra S  



CH Charles March 28, 2022 02:50 AM UTC

Hi,

I was not able to make use of the image preview method provided among the documentations mentioned by you as l don't know how to create it in grid dialog. So, I have used the normal uploader. The uploader is working fine but l want it to be bind with EmployeeId so that when l want to edit a record in the grid it would be populated by calling EmployeeId. Below are the codes that l have tried. Kindly assist




<p>Department mubi</p>
<div>
    <ejs-grid [dataSource]='data | async'
    [editSettings]= 'editSettings'
    [toolbar]='toolbar'
     allowPaging='true'
     height="300"
     [pageSettings]='pageSettings'
     allowSorting= 'true'
     (dataStateChange)='dataStateChange($event)'
     (dataSourceChanged)='dataSourceChanged($event)'>
     <e-columns>
        <e-column
        field="EmployeeId" headerText="EmployeeID" width="80" textAlign="Left" isPrimaryKey="true" type="text" ></e-column>
        <e-column field= "EmployeeName" headerText="EmployeeName" width="100"  > </e-column>    
        <e-column field= "Department" headerText="Department"  width="100"  ></e-column>  
        <e-column field= "DateOfBirth" headerText="DOB" width="90" editType="datepickeredit" format="yMd"></e-column>  
        <e-column field= "PhotoFileName" headerText="Employee Image" width="120" [edit]="dpParams" >
         <ng-template #template let-data>
            <div class="image">
                <img src="{{data.EmployeeId}}" alt="{{data.EmployeeId}}" />
            </div>
         </ng-template>
         </e-column>            
     </e-columns>
     </ejs-grid>
    </div>


import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { DataSourceChangedEventArgs, DataStateChangeEventArgs, EditSettingsModel, ToolbarItems, IEditCell } from '@syncfusion/ej2-grids';
import { Column, GridComponent } from '@syncfusion/ej2-angular-grids';
import { Observable } from 'rxjs';
import { SharedService } from 'src/app/shared.service';
import { Uploader } from '@syncfusion/ej2-inputs';
import { state } from '@angular/animations';

@Component({
selector: 'app-root',
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
encapsulation: ViewEncapsulation.None,
providers: [SharedService]
})
export class AppComponent implements OnInit {  
  public data: Observable<DataStateChangeEventArgs>;
  public editSettings: EditSettingsModel;    
  public toolbar: ToolbarItems[];      
  public pageSettings: Object;
  public elem: HTMLElement;
  public uploadObj: Uploader;
  public strm: any;
  public dpParams: IEditCell;
 
 
  @ViewChild('grid')
  public grid: GridComponent;    

  constructor(public service: SharedService){
     this.data = service;
  }
 
  ngOnInit(): void {  
    this.editSettings = {allowEditing: true, allowAdding: true, allowDeleting: true, showDeleteConfirmDialog:true, mode: 'Dialog'};
    this.toolbar = ["Add", "Edit", "Delete", "Update", "Cancel"];      
    this.pageSettings = { pageSize: 5 };
    let state = { skip: 0, take: 5 };
    this.service.execute(state);

    this.dpParams = {
      //cellEditTemplate
      create: () => {
        // Input element is created and returned for appending the Uploader control
        this.elem = document.createElement('input');
        return this.elem;
      },
      read: () => {
        return this.strm;
      },
      destroy: () => {
        // Uploader is destroyed on edit save/close
        this.uploadObj.destroy();
      },
      write: state => {
        this.uploadObj = new Uploader({
          asyncSettings: {
            saveUrl:
              'http://localhost:5000/api/Employee/SaveFile',
            removeUrl:
              'http://localhost:5000/api/Employee/SaveFile'
          },
          success: onUploadSuccess.bind(this),
          failure: onUploadFailure
        });
        this.uploadObj.appendTo(this.elem);
        function onUploadSuccess(state) {
          if (state.operation === "UploadPhoto") {          
            var file = state.file.rawFile;          
            var reader = new FileReader();
            reader.readAsDataURL(file);

            reader.onload = function() {
              this.strm = reader.result;
            }.bind(this);

            reader.onerror = function(error) {
              console.log('Error: ', error);
            };
          }
        }
        function onUploadFailure(state) {
          console.log('File failed to upload');
        }
      }
    };  

  }
  public dataStateChange(state: DataStateChangeEventArgs): void{
    this.service.execute(state);
  }

  public dataSourceChanged(state: DataSourceChangedEventArgs): void {
    if(state.action === "add") {
      this.service.addRecord(state).subscribe(() => {
        state.endEdit();
      });
    }

    else if(state.action === "edit") {
      this.service.updateRecord(state).subscribe(() => {
        state.endEdit();
      });
    }

    else if(state.requestType === "delete") {
      this.service.deleteRecord(state).subscribe(() => {
        state.endEdit();
      });
    }  
  }  
}
 



import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { DataSourceChangedEventArgs, DataStateChangeEventArgs} from '@syncfusion/ej2-grids';
import { Subject } from 'rxjs/Subject';
import { map } from 'rxjs/operators';
import { Injectable } from '@angular/core';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
};

@Injectable({
  providedIn: 'root'
})
export class SharedService extends Subject<DataStateChangeEventArgs>{

  public APIUrl= 'http://localhost:5000/api/Employee';
  public PhotoUrl= 'http://localhost:5000/api/Photos';

  constructor(private http:HttpClient) {
      super();
   }

  public execute(state: any): void{
      this.getEmpList(state).subscribe(x =>
        super.next(x as DataStateChangeEventArgs)
    );
  }

  getEmpList(state?: any):Observable<any[]>{
    return this.http.get<any>(this.APIUrl).pipe(
      map(
        (response: any) =>
        <any>{
          result:
            state.take > 0
              ? response.slice(state.skip, state.take)
              : response,
            count: response.length
        }
      )
    );  
  }
 
  addRecord(state: DataSourceChangedEventArgs): Observable<any> {
    return this.http.post<any>(this.APIUrl, state.data, httpOptions);
  }

  updateRecord(state: DataSourceChangedEventArgs): Observable<any> {
    return this.http.put<any>(this.APIUrl, state.data, httpOptions
    );
  }
 
  deleteRecord(state: any): Observable<any> {
    const id = state.data[0].EmployeeId;
    const url = `${this.APIUrl}/${id}`;
    return this.http.delete<any>(url, httpOptions);
  }

 
  UploadPhoto(state:any): Observable<any>{
    return this.http.post<any>(this.APIUrl+'/SaveFile', state.data, httpOptions);
  }

}
 


PS Pavithra Subramaniyam Syncfusion Team March 29, 2022 01:07 PM UTC

Hi Charles,


You can get the currently edited row data using "state.rowData" inside the “write” method. Using this you can customize the Uploader component as per your requirement.


write: (state) => {

        alert(state.rowData.EmployeeID);

        this.uploadObj = new Uploader({

         .  .  .

        });

        this.uploadObj.appendTo(this.elem);

        .  .  .

    };

 


If this does not meet your requirement, please share the below details that will be helpful for us to provide a better solution as early as possible.


  1. How do you want to bind the EmployeeID with the uploader component?
  2. Do you want to show the image for the corresponding EmployeeID while editing?


Regards,

Pavithra S



CH Charles March 30, 2022 07:51 AM UTC

Hi Pavithra,

1. I don't want the uploader to auto upload image into the folder Photos at the backend. I want to manually upload image as soon as the grid save button is clicked. When l click the save button l want it to save all the data in the field i.e. EmployeeId, EmployeeName, Department, DOB, PhotoFileName at once into the server.

2. Yes l also want to show the image for the corresponding EmployeeId while editing




PS Pavithra Subramaniyam Syncfusion Team March 31, 2022 01:17 PM UTC

Hi Charles,


Thanks for sharing the details.


Query#1: I want to manually upload image as soon as the grid save button is clicked. When l click the save button l want it to save all the data in the field i.e. EmployeeId, EmployeeName, Department, DOB, PhotoFileName at once into the server.


You can achieve your requirement by setting the “autoUpload” property of the uploader component as “false”.This will restrict the file uploading. And you can get the selected file information inside the “selected” event handler. So you can store this information in a variable and set it to the edited data inside the “actionComplete” event with “save” requestType. Please refer to the below code example and API link for more information.


this.editparams = {

     .  .  .

      write: (state) => {

        this.uploadObj = new Uploader({

          asyncSettings: {

            saveUrl: 'http://localhost:5000/api/Employee/SaveFile',

            removeUrl: 'http://localhost:5000/api/Employee/SaveFile',

          },

          autoUpload: false,

          selected: select.bind(this),

          success: onUploadSuccess.bind(this),

          failure: onUploadFailure,

        });

        this.uploadObj.appendTo(this.elem);

        function select(args) {

          this.uploadedFile = args.filesData[0];

        }

      },

    };

    .  .  .

  actionBegin(args) {

    if (args.requestType == 'save') {

      this.uploadObj.upload();

      args.data['PhotoFileName '] = this.uploadedFile.name;

    }

  }

 


API        :  https://ej2.syncfusion.com/angular/documentation/api/uploader/#autoupload

                 https://ej2.syncfusion.com/angular/documentation/api/uploader/#selected

                 https://ej2.syncfusion.com/angular/documentation/api/uploader/#upload (for manually uploading the file)

                 https://ej2.syncfusion.com/angular/documentation/api/grid/#actioncomplete


Query#2: Yes l also want to show the image for the corresponding EmployeeId while editing


Before providing a solution, please share the format of the image (ex: base64 or file location) that will be helpful for us.


Regards,

Pavithra S




CH Charles March 31, 2022 09:20 PM UTC

Hi Pavithra,

It's still didn't work.

Nevertheless, I want to work with forms and will like to achieve exactly (inputs, image uploader, and panels) that is shown on the picture attached. I don't want to make use of the grid/grid dialog. I want to create form with fields that save data to the server. Am using syncfusion angular. Kindly assist


profie.png



PS Pavithra Subramaniyam Syncfusion Team April 11, 2022 04:50 AM UTC

Hi Charles,


Regarding your query with Syncfusion inputs and uploader components, we have created a new ticket under your account. So please follow that ticket for more updates.


Regards,

Pavithra S


Loader.
Up arrow icon