We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

How to delete record in grids using Observables method

Hi,

I can both insert and update a record in grids into the server but can not delete any record. I have read documentations and watch videos on how to perform CRUD using the Observables but l still can not delete record from the server. kindly assist.



ejs-grid [dataSource]="data | async"
[editSettings]= "editSettings"
[toolbar]="toolbar"
 allowPaging="true"
 height="300"
 (dataStateChange)="dataStateChange($event)"
 (dataSourceChanged)="dataSourceChanged($event)"
><e-columns>
    <e-column
    field="DepartmentId"
     headerText="DepartmentID"
      width="80" textAlign="Left"
      isPrimaryKey="true"
      type="text"
      ></e-column>
  <e-column
       field= "DepartmentName"
       headerText="DepartmentName"
       width="120"
  ></e-column>    
</e-columns>
</ejs-grid>


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

@Component({
selector: 'app-root',
templateUrl: "app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {    
 
    public data: Observable<DataStateChangeEventArgs>;
    public editSettings: EditSettingsModel;    
    public toolbar: ToolbarItems[];

   
   
    @ViewChild('grid')
    public grid: GridComponent;
       
    constructor(public service: SharedService){
       this.data = service;
    }

    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();
        });
      }
    }

    ngOnInit(): void {  
      this.editSettings = {allowEditing: true, allowAdding: true, allowDeleting: true, showDeleteConfirmDialog:true, mode: 'Dialog'
    };    

    this.toolbar = ["Add", "Edit", "Delete", "Update", "Cancel"];        
    const state: any = {skip: 0, take: 7};
    this.service.execute(state);  
  }  
}
   



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


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

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

  public APIUrl= "http://localhost:5000/api/Department";

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

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

  getDepList(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);
  }
 
   deleteRecord(state: any): Observable<any> {
    const id = state.data[0].id;
    const url = `${this.APIUrl}/${id}`;

    return this.http.delete<any>(url, httpOptions);
  }

  updateRecord(state: DataSourceChangedEventArgs): Observable<any> {
    return this.http.put<any>(this.APIUrl, state.data, httpOptions
    );
  }  
}




68 Replies

PS Pavithra Subramaniyam Syncfusion Team March 7, 2022 09:07 AM UTC

Hi Charles, 
 
Thanks for contacting Syncfusion support. 
 
We have prepared a simple sample with the shared code and tried to replicate the reported behavior. But it was unsuccessful at our end. The delete action is working fine at our end. Find the below sample for your reference. 


Kindly share the below details to replicate the issue from our end. 

  1. Share the Sycnfusion package version
  2. Is there any script error?
  3. Confirm whether the “state.endEdit();” code is hit for delete action?
  4. Share the video demo of the reported behavior.
  5. Share the issue reproducible sample or try to make the issue in given sample.
 
Regards, 
Pavithra S 



CH Charles March 8, 2022 04:18 AM UTC

1. Package 19.5.4

2. Each time l try to delete a row it would complains of this error http://localhost:5000/api/Department/undefined

Bad request 404.

3. The moment l hit the delete button it would hang and it would allow any further action unless l refresh the page.




PS Pavithra Subramaniyam Syncfusion Team March 8, 2022 08:47 AM UTC

Hi Charles, 
 
Thanks for sharing the details. 
 
From the 404 error, we could see that you are passing an undefined value instead of the primary key column value inside the deleteReocrd method of your service. So we suggest to send the key value with the delete API URL which will resolve this issue. 
 
deleteRecord(state: any): Observable<any> { 
    const id = state.data[0].DepartmentID; 
    const url = `${this.APIUrl}/${id}`; 
    return this.http.delete<any>(url, httpOptions); 
  } 
 
 
Please get back to us if you need further assistance on this. 
 
Regards, 
Pavithra S 



PS Pavithra Subramaniyam Syncfusion Team March 9, 2022 11:34 AM UTC

Hi Charles, 
 
From your code example, we could see that you are using HttpModule in you service file which is the cause of the reported behavior. Since HttpClient.get() applies response.json() automatically we need not to call it explicitly. So, we suggest you change return value in “getData” method as below code example. 
 
 protected getData(state: DataStateChangeEventArgs): Observable<DataStateChangeEventArgs> { 
    .  .  . 
 
    return this.http 
      .get( 
        `${this.BASE_URL}?${pageQuery}${sortQuery}&$inlinecount=allpages&$format=json`) 
      .pipe(map((response: any) => response)) 
      .pipe( map( 
          (response: any) => 
            <DataResult>{ 
              result: response['d']['results'], 
              count: parseInt(response['d']['__count'], 10), 
            } 
        ) 
      ) 
      .pipe((data: any) => data); 
  } 
 
 
Regards, 
Pavithra S 



CH Charles March 9, 2022 12:47 PM UTC

Hi Pavithra,

Thank you for the solutions you provided as my delete method is now working fine.

I'm having problem with paging in grid. I did change my code to as to try the example that l found in your documentation but at the moment my grid is no longer populating data from the server. I want my grid to perform paging like in the sample (see link below). Kindly assist

https://stackblitz.com/edit/angular-kqu7vy-qg3vwz?file=app.component.ts

I got this script error: response.json is not a function


import
{ BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { GridAllModule, EditService, ToolbarService, PageService } from '@syncfusion/ej2-angular-grids';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
GridAllModule,
HttpClientModule
],
providers: [ EditService, ToolbarService, PageService],
bootstrap: [AppComponent]
})
export class AppModule { }


import { Component, OnInit, ViewChild } from '@angular/core';
import { DataSourceChangedEventArgs, DataStateChangeEventArgs, EditSettingsModel, ToolbarItems } from '@syncfusion/ej2-grids';
import { Observable } from 'rxjs';
import {SharedService} from './shared.service';
import { GridComponent } from '@syncfusion/ej2-angular-grids';
import { PageSettingsModel } from '@syncfusion/ej2-angular-grids';



@Component({
selector: 'app-root',
templateUrl: "app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
public data: Observable<DataStateChangeEventArgs>;
public editSettings: EditSettingsModel;
public toolbar: ToolbarItems[];
public pageSettings: Object;

@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);
}

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 { Component, OnInit, ViewChild } from '@angular/core';
import { DataSourceChangedEventArgs, DataStateChangeEventArgs, EditSettingsModel, ToolbarItems } from '@syncfusion/ej2-grids';
import { Observable } from 'rxjs';
import {SharedService} from './shared.service';
import { GridComponent } from '@syncfusion/ej2-angular-grids';
import { PageSettingsModel } from '@syncfusion/ej2-angular-grids';



@Component({
selector: 'app-root',
templateUrl: "app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
public data: Observable<DataStateChangeEventArgs>;
public editSettings: EditSettingsModel;
public toolbar: ToolbarItems[];
public pageSettings: Object;

@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);
}

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 { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { DataStateChangeEventArgs, DataSourceChangedEventArgs, Sorts, DataResult } from '@syncfusion/ej2-grids';
import { Subject } from 'rxjs/Subject';
import { map } from 'rxjs/operators';
import 'rxjs/add/operator/map';

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

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

public APIUrl= 'http://localhost:5000/api/Department';

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

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

protected getDepList(state: DataStateChangeEventArgs): Observable<DataStateChangeEventArgs> {
const pageQuery = `$skip=${state.skip}&$top=${state.take}`;
let sortQuery = '';
const d = 'd';
const results = 'results';
const count = '__count';
if ((state.sorted || []).length) {
sortQuery = `&$orderby=` + state.sorted.map((obj: Sorts) => {
return obj.direction === 'descending' ? `${obj.name} desc` : obj.name;
}).reverse().join(',');
}

return this.http
.get(`${this.APIUrl}?${pageQuery}${sortQuery}&$inlinecount=allpages&$format=json`)
.map((response: any) => response.json())
.map((response: any) => ({
result: response[d][results],
count: parseInt(response[d][count], 10)
} as DataResult))
.pipe((data: any) => data);
}
addRecord(state: DataSourceChangedEventArgs): Observable {
return this.http.post(this.APIUrl, state.data, httpOptions);
}

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





CH Charles March 10, 2022 02:00 AM UTC

Hi Pavithra

I have done exactly what you have asked me to do, but still my grid is no longer population data from the server let alone paging as l keep getting this error:

ERROR TypeError: Cannot read properties of undefined (reading 'results')

    at MapSubscriber.project (main.js:57:34)

    at MapSubscriber._next (vendor.js:222861:35)

    at MapSubscriber.next (vendor.js:85097:18)

    at MapSubscriber._next (vendor.js:222867:26)

    at MapSubscriber.next (vendor.js:85097:18)

    at FilterSubscriber._next (vendor.js:245638:30)

    at FilterSubscriber.next (vendor.js:85097:18)

    And so on.



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

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

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

private APIUrl= 'http://localhost:5000/api/Department';

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

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

protected getDepList(state: DataStateChangeEventArgs): Observable<DataStateChangeEventArgs> {
const pageQuery = `$skip=${state.skip}&$top=${state.take}`;
let sortQuery = '';
const d = 'd';
const results = 'results';
const count = '__count';
if ((state.sorted || []).length) {
sortQuery = `&$orderby=` + state.sorted.map((obj: Sorts) => {
return obj.direction === 'descending' ? `${obj.name} desc` : obj.name;
}).reverse().join(',');
}

return this.http
.get(
`${this.APIUrl}?${pageQuery}${sortQuery}&$inlinecount=allpages&$format=json`)
.pipe(map((response: any) => response))
.pipe( map(
(response: any) =>
<DataResult>{
result: response[d][results],
count: parseInt(response[d][__count], 10),
}
)
)
.pipe((data: any) => data);
}



PS Pavithra Subramaniyam Syncfusion Team March 10, 2022 10:35 AM UTC

Hi Charles, 

We have used the same code you have shared for the OrderService, but the paging is working fine at our end. Please refer to the below sample. 


Since the reported issue is from the service code of your sample and not from the Syncfusion package please refer to the below reference links for more information which might help you to find the exact reason for the issue. 


Regards, 
Pavithra S 



CH Charles March 16, 2022 04:50 PM UTC

Hi Pavithra,

From the provided demo example l was able to create sidebar plus tree view project and now I am trying to create router links for each sidebar menu button but it's not working. Kindly assist


import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { EmployeeComponent } from './employee/employee.component';
import { CustomersComponent } from './customers/customers.component';

const routes = [
 
  { path: 'employees', component: EmployeeComponent, text: 'Employees' },
  { path: 'customers', component: CustomersComponent, text: 'Customers' }

];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }



<div id="wrapper">
<div class="col-lg-12 col-sm-12 col-md-12" id="sidebar-section">
<div class="col-lg-12 col-sm-12 col-md-12">
<div class="main-header" id="header-section">
<ul class="header-list">
<li class="float-left header-style icon-menu" id="hamburger" (click)="openClick()">li>
<li class="float-left header-style nav-pane"><b>Navigation Paneb>li>
ul>
div>
<ejs-sidebar id="sidebar-treeview" class="dock-menu" #sidebarTreeviewInstance [field]='field'(nodeSelected)="loadRoutingContent($event)" [enableDock]='enableDock' [width]='width' [dockSize]='dockSize' (created)="onCreated($event)" style="visibility: hidden"
[mediaQuery]='mediaQuery' [target]='target' (close)="onClose($event)">
<div class="main-menu">
<div>
<ejs-treeview id="main-treeview" #treeviewInstance [fields]='field' expandOn='Click'>ejs-treeview>

div>
div>
ejs-sidebar>

<div class="main-content" id="main-text">
<div class="sidebar-content">
<h2 class="sidebar-heading"> Responsive Sidebar With Treeviewh2>
<p class="paragraph-content"> This is a graphical aid for visualising and categorising the
site,
in the style of an expandable and collapsable treeview component. It auto-expands to
display
the node(s), if any, corresponding to the currently viewed title, highlighting that node(s)
and its ancestors. Load-on-demand when expanding nodes is available where supported
(most graphical browsers), falling back to a full-page reload. MediaWiki-supported caching,
aside from squid, has been considered so that unnecessary re-downloads of content are
avoided
where possible. The complete expanded/collapsed state of the treeview persists across page
views
in most situationsp>
<div class="line">div>
<h2 class="sidebar-heading">Lorem Ipsum Dolorh2>
<p class="paragraph-content">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.p>
<div class="line">div>
<h2 class="sidebar-heading"> Lorem Ipsum Dolorh2>
<p class="paragraph-content">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.p>
div>
div>
div>
div>
div>


import { Component, OnInit, ViewChild} from '@angular/core';
import { SidebarComponent, TreeViewComponent, NodeSelectEventArgs } from '@syncfusion/ej2-angular-navigations';
import { Router } from '@angular/router';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{

@ViewChild('sidebarTreeviewInstance')
public sidebarTreeviewInstance: SidebarComponent;
@ViewChild('treeviewInstance')
public treeviewInstance: TreeViewComponent;
public width: string = '220px';
public enableDock: boolean = true;
public dockSize:string ="44px";
public mediaQuery: string = ('(min-width: 600px)');
public target: string = '.main-content';
public field:Object;

public data: Object[] = [
{
nodeId: '01', nodeText: 'Main', iconCss: 'icon-microchip icon',
},
{
nodeId: '02', nodeText: 'Customers', iconCss: 'icon-docs icon', url: 'customers',
},
{
nodeId: '03', nodeText: 'Human Resources', iconCss: 'icon-th icon',
nodeChild: [
{ nodeId: '03-01', nodeText: 'Employee', iconCss: 'icon-circle-thin icon' },
{ nodeId: '03-02', nodeText: 'Finance', iconCss: 'icon-circle-thin icon' },
]
},
];

constructor(private router: Router) {
this.field = { dataSource: this.data, id: 'nodeId', text: 'nodeText', child: 'nodeChild', expanded: 'expanded', selected: 'selected' };
}

public loadRoutingContent(args: NodeSelectEventArgs): void {
let data1:any = this.treeviewInstance.getTreeData(args.node);
let routerLink: string = data1[0].url;
this.router.navigate([routerLink]);
}

ngOnInit() {
this.router.navigate(['employees']);
}

public onCreated(args: any) {
this.sidebarTreeviewInstance.element.style.visibility = '';
}
public onClose(args: any) {
this.treeviewInstance.collapseAll();
}
openClick() {
if(this.sidebarTreeviewInstance.isOpen)
{
this.sidebarTreeviewInstance.hide();
this.treeviewInstance.collapseAll();
}
else {
this.sidebarTreeviewInstance.show();
this.treeviewInstance.expandAll();
}
}
}


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

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SidebarModule, TreeViewModule } from '@syncfusion/ej2-angular-navigations';
import { EmployeeComponent } from './employee/employee.component';
import { CustomersComponent } from './customers/customers.component';
import { APP_BASE_HREF } from '@angular/common';

@NgModule({
declarations: [
AppComponent,
EmployeeComponent,
CustomersComponent
],
imports: [
BrowserModule,
AppRoutingModule,
SidebarModule,
TreeViewModule
],
providers: [{ provide: APP_BASE_HREF, useValue: window.location.pathname }],
bootstrap: [AppComponent]
})
export class AppModule { }





IL Indhumathy Loganathan Syncfusion Team March 17, 2022 10:13 AM UTC

Hi Charles, 
 
We have prepared a simple sample to perform navigation on a TreeView node click. We have used the TreeView nodeSelected event to perform routing. Please see the link below for the sample.. 
 
 
You need to set the navigated page content as the main content of the Sidebar, as done in the above sample. Please try the above way to achieve your requirement. Please get back to us if you need any further assistance. 
 
Regards, 
Indhumathy L 



CH Charles March 18, 2022 02:57 PM UTC

Hi Indhumathy,

Thank you for your suggestions. I ave discovered where l made the mistake in my codes. I have fixed the problem

Regards



CH Charles March 21, 2022 12:22 AM UTC

photoOfEmployee.png 


Hi Indhumathy,

Iwant to create a syncfusion grid modal form like the above picture.  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 and how to populate grid that would contains photo etc? I'm using syncfusion angular. Kindly assist





PS Pavithra Subramaniyam Syncfusion Team March 21, 2022 02:12 PM 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 May 8, 2022 09:25 PM UTC

Hello,

I can load the grid from the server but pagination is not working as it keeps signally waiting. Kindly assist me to fix paging issue on my grid



import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DataStateChangeEventArgs, DataSourceChangedEventArgs, Sorts, DataResult } from '@syncfusion/ej2-angular-grids'
import { Observable } from 'rxjs';
import { Subject } from 'rxjs';
import { map } from 'rxjs/operators';
import { EmpModel } from './customer/emp/sharedemp/emp-model.model';
import 'rxjs/add/operator/map';

@Injectable({
providedIn: 'root'
})
export class SharedService extends Subject<DataStateChangeEventArgs> {
private EmpUrl = 'http://localhost:5000/api/Employee';

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

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

/** GET all data from the server */
getAllData(): Observable<any[]> {
return this.http
.get<EmpModel[]>(this.EmpUrl)
.map(
(response: any) =>
<any>{
result: response,
count: response.length,
}
)
.map((data: any) => data);
}

}



import { Component, OnInit, Inject } from '@angular/core';
import { Observable } from 'rxjs';
import { EmplistserviceService } from './emplistservice.service';
import { DataStateChangeEventArgs } from '@syncfusion/ej2-grids';

@Component({
selector: 'app-employee-list',
templateUrl: './employee-list.component.html',
styleUrls: ['./employee-list.component.css'],
providers: [EmplistserviceService],
})
export class EmployeeListComponent implements OnInit {

public data: Observable<DataStateChangeEventArgs>;
public pageSettings: Object;
public state: DataStateChangeEventArgs;
constructor(public service:EmplistserviceService) {
this.data = service;
}

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

ngOnInit(): void {
this.pageSettings = { pageSize: 5 };
let state = { skip: 0, take: 5 };
this.service.execute(state);
}
}


<div class="control-section">
<ejs-grid [dataSource]='data | async' allowPaging= 'true' [pageSettings]='pageSettings' allowSorting= 'true' allowGrouping= 'true'
( dataStateChange)'dataStateChange($event) >
<e-columns>
<e-column field= "EmployeeId" headerText="Employee ID" width="130" >e-column>
<e-column field="EmployeeName" headerText="Employee Name" width="150">
e-column>
<e-column field= "Department" headerText="Department" width="200">e-column>
<e-column field= "DateOfBirth" headerText="DateOfBirth" width="150">e-column>
<e-column field= "PhotoFileName" headerText="PhotoFileName" width="150">e-column>
e-columns>
ejs-grid>


div>





PS Pavithra Subramaniyam Syncfusion Team May 10, 2022 05:26 AM UTC

Hi Charles,


We have tried to reproduce the issue at our end, but it is working fine with the provided code. Please refer to the below sample link for more information.


https://stackblitz.com/edit/angular-n6yvrn?file=main.ts


So could you please share the below details that will be helpful for us to provide a better solution as early as possible?


  1. Is there any script error?
  2. Share an issue reproducible sample
  3. Or try to reproduce the issue in the given sample if possible.


Regards,

Pavithra S



CH Charles May 11, 2022 09:40 AM UTC

Hi Pavithra,

In the link that you provided the paging is not working. That is, when you click page 2 or next it would change but the grid contents remain the same. It's expected that when one click page 2 then more data from the server would be show on the grid.

Answers to your questions above:

  1. yes there is script error. see below


constructor(private http: Http) {
super();
}
There was error with the above line of code so l change it to Http:HttpClient
constructor(private http:HttpClient ) {
super();
}
And l got this error 'TypeError: response.json is not a function'
So l removed the .Json() (l also tried by removing the entire line) and it gives this error

TypeError: Cannot read properties of undefined (reading 'results')


3. I've tried what is found on the link and the errors in answer number 1 was what l got.

What l really want is that the grid should populate all records from the server to the browser. For example Customers table is created in the database which contains 200 records of customers. So l want to load all the 200 records of customer to the browser (grid) via the server. Then the grid should only show 10 records of customer per page on the browser. If page 1 shows 1-10 customer record, then when l click page 2 it should show 11-20 customers record etc



PS Pavithra Subramaniyam Syncfusion Team May 11, 2022 02:20 PM UTC

Hi Charles,


Since you’re using the “Custom Binding” in Grid components Grid will send the current page details to the “dataStateChange” event. Inside this event, you need to call your service and return the required data for that Grid page. But in your code, you are returning all the data for all calls.
That’s why it looks like the pagination is not working. If you want to load all the data at initial rendering and do pagination without sending further requests to the server, then it will act as local data binding and all the Grid data actions and CRUD actions will be done locally.


Could you please confirm whether you want to do only the pagination or all the Grid actions (page, filter, sort, CRUD, etc.) locally without accessing the server again? Based on this we will provide a solution as early as possible.


Regards,

Pavithra S



CH Charles May 17, 2022 09:35 AM UTC

Hi Pavithra,

I have solved the problem. Thank you.

I'm having issue with passing selected grid row to textboxes in another component.

In your documentations there is dialog popup property that is bind to a grid for adding and editing data, but l don't want to make use of that. I have created an external form called Employee Form in a component and Employee List (grid) in another component. So when i select a row in grid and click on my custom 'Edit the Employee' button then the external form textboxes should be filled with that grid row contents. This is to enable me to proceed with other forms that would depend on the Employee form. Kindly assist

<button ejs-button iconCss="" iconPosition="Right" class="submit-btn e-btn e-primary" style="float:
right; margin:15px ;padding-left: 25px;">Editbutton>
div>
<div>
<ejs-grid [dataSource]='data | async'
allowPaging= 'true'
[pageSettings]='pageSettings'
allowSorting= 'true'
allowGrouping= 'true'
(dataStateChange)= 'dataStateChange($event)' >
<e-columns>
<e-column field="EmployeeId" headerText="Employee ID" width="50" [visible]="false" [isPrimaryKey]="true"> e-column>
<e-column field="EmployeeName" headerText="Employee Name" width="100"> e-column>
<e-column field="Department" headerText="Department" width="100"> e-column>
<e-column field="DateOfBirth" headerText="Date Of Birth" width="70"> e-column>
<e-column field="PhotoFileName" headerText="Photo" width="90"> e-column>
e-columns>
ejs-grid>
div>



import { Component, OnInit } from '@angular/core';
import {EditSettingsModel, ToolbarItems, DataStateChangeEventArgs, CommandModel} from '@syncfusion/ej2-angular-grids';
import { Observable } from 'rxjs/Observable';
import { SharedempService } from '../emp/sharedemp/sharedemp.service';


@Component({
selector: 'app-emp-list',
templateUrl: './emp-list.component.html',
styleUrls: ['./emp-list.component.css']
})
export class EmpListComponent implements OnInit {

public data: Observable<DataStateChangeEventArgs>;
public editOptions: EditSettingsModel;
public toolbarOptions: ToolbarItems[];
public pageSettings: Object;
public state: DataStateChangeEventArgs;
public commands: CommandModel[];

constructor(public service:SharedempService) {
this.data = service;
}

public dataStateChange(state: DataStateChangeEventArgs): void {
this.service.execute(state);
}
public ngOnInit(): void {
this.commands = [{buttonOption: { iconCss: ' e-icons e-print-layout', cssClass: 'e-flat' }}];
this.pageSettings = { pageSize: 5, pagecount:5 };
let state = { skip: 0, take: 5 };
this.service.execute(state);
}
}


Employee Form component

<div class="col-lg-12 control-section">
<div class="content-wrapper" style="margin-bottom: 25px;">
<div class="formtitle">
<span>Add Employee Detailsspan>
div>

<form id="formId" [formGroup]="reactForm" #form="ngForm" (submit)="onSubmit(form)" class="form-horizontal" novalidate="">

<div class="form-group">
<div class="e-float-input">
<input id="EmployeeId" type="EmployeeId" formControlName="EmployeeId" [(ngModel)]="service.formData.EmployeeId">
<span class="e-float-line">span>
<label for="EmployeeId" class="e-float-text">EmployeeIdlabel>
div>
div>

<div class="form-group">
<div class="e-float-input">
<input id="EmployeeName" type="text" formControlName="EmployeeName" [(ngModel)]="service.formData.EmployeeName">
<span class="e-float-line">span>
<label for="EmployeeName" class="e-float-text">Employee Namelabel>
div>
div>

<div class="form-group">
<div class="e-float-input">
<ejs-dropdownlist id="Department" name="Department" formControlName="Department" [dataSource]='data' [fields]='fields' [placeholder]='text' [query]='query'
[(ngModel)]="service.formData.Department" floatLabelType='auto'>ejs-dropdownlist>
<span class="e-float-line">span>
div>
div>

<div class="form-group">
<div class="e-float-input">
<ejs-datepicker id="DateOfBirth" type="date" formControlName="DateOfBirth" placeholder="dob" [(ngModel)]="service.formData.DateOfBirth"
floatLabelType='auto'>ejs-datepicker>
<span class="e-float-line">span>
div>
div>

<div class="form-group">
<div class="e-float-input">
<input id="PhotoFileName" type="text" formControlName="PhotoFileName" [(ngModel)]="service.formData.PhotoFileName">
<span class="e-float-line">span>
<label class="e-float-text" for="PhotoFileName">photolabel>
div>
div>
<div class="row">
<div style="width: 320px;margin:0px auto;height: 100px;padding-top: 25px;">
<div style="display: inline-block;">
<button id="validateSubmit" class="samplebtn e-control e-btn e-primary" type="submit" style="height:40px;width: 150px;" >Add Employeebutton>
div>
<div style="float: right;">
<button id="resetbtn" class="samplebtn e-control e-btn" type="reset" style="height:40px;width: 150px;" data-ripple="true">Clearbutton>
div>
div>
div>
form>
div>
div>



import { Component, OnInit } from '@angular/core';
import { SharedempService } from '../sharedemp/sharedemp.service';
import { NgForm } from '@angular/forms';
import { FormControl, FormGroup, Validators, FormsModule, AbstractControl } from '@angular/forms';
import { FormValidators } from '@syncfusion/ej2-angular-inputs';
import { HttpClient } from '@angular/common/http';
import { DataManager, WebApiAdaptor, Query } from '@syncfusion/ej2-data';


@Component({
selector: 'app-emp',
templateUrl: './emp.component.html',
styles: [`./emp.component.css`],
providers: [SharedempService]
})

export class EmpComponent implements OnInit {
reactForm: FormGroup;
constructor(private http: HttpClient, public service:SharedempService){
this.reactForm = new FormGroup({
'EmployeeId': new FormControl('', [FormValidators.required]),
'EmployeeName': new FormControl(''),
'Department': new FormControl(''),
'DateOfBirth': new FormControl(''),
'PhotoFileName': new FormControl(''),
});
}

public data: DataManager = new DataManager({
url: 'http://localhost:5000/api/',
adaptor: new WebApiAdaptor,
crossDomain: true
});

public fields: Object = { text: 'DepartmentName', value: 'DepartmentName' };
public query: Query = new Query().from('Department').select(['DepartmentName']).take(6);
public text: string = "Select a Department";

public ngOnInit(): void {
let formId: HTMLElement = <HTMLElement>document.getElementById('formId');
document.getElementById('formId').addEventListener(
'submit',
(e: Event) => {
e.preventDefault();
if (this.reactForm.valid) {
alert('Customer details added!');
this.reactForm.reset();
} else {
// validating whole form
Object.keys(this.reactForm.controls).forEach(field => {
const control = this.reactForm.get(field);
control.markAsTouched({ onlySelf: true });
});
}
});
}

onSubmit(form: NgForm){
this.service.postEmodel().subscribe(
res =>{
},
err =>{console.log(err); }
);
}

get check() { return this.reactForm.get('check'); }
get EmployeeId() { return this.reactForm.get('EmployeeId'); }
get EmployeeName() { return this.reactForm.get('EmployeeName'); }
get Department() { return this.reactForm.get('Department'); }
get DateOfBirth() { return this.reactForm.get('DateOfBirth'); }
get PhotoFileName() { return this.reactForm.get('PhotoFileName'); }


}






PS Pavithra Subramaniyam Syncfusion Team May 17, 2022 01:40 PM UTC

Hi Charles,


You can get the currently selected Grid record details by using the “getSelectedRecords” method. So, while clicking the Edit button, you can pass these details using the decorators like “@Input” and “@Output” if the two components are parent and child. Otherwise, you can use the angular Service to pass the data between the components. Please refer to the below API and reference links for more information.


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


Reference          : https://www.c-sharpcorner.com/blogs/pass-data-between-component-to-another-component-in-angular

  https://stackoverflow.com/questions/69150472/how-to-pass-data-from-one-component-to-another-dynamically-without-parent-child


Also, we have inbuilt support for adding a template in the default edit dialog. So, you can add the customized editor components in the Dialog without defining a separate component. Please refer to the below demo and documentation link for more information.


Demo   : https://ej2.syncfusion.com/angular/documentation/grid/editing/template-editing/#reactive-forms

                https://ej2.syncfusion.com/angular/demos/#/material/grid/dialog-reactive-form


Please get back to us if you need further assistance on this.


Regards,

Pavithra S



CH Charles May 20, 2022 03:44 PM UTC

Hi Pavithra,

Thank you. I have not be able to see a good example on how to use  getSelectedRecords”. I have tried the @Input and @output decorator but was not successful using Syncfusion angular input controls.

I have also tried using the Angular Service but I'm having issues passing data from grid to input control on form, The codes below are what I've tried. Kindly assist.

import { Component, OnInit, ViewChild } from '@angular/core';
import { SharedempService } from '../sharedemp/sharedemp.service';
import { NgForm } from '@angular/forms';
import { FormControl, FormGroup, Validators, FormsModule, AbstractControl } from '@angular/forms';
import { FormValidators } from '@syncfusion/ej2-angular-inputs';
import { HttpClient } from '@angular/common/http';
import { DataManager, WebApiAdaptor, Query } from '@syncfusion/ej2-data';
import {EditSettingsModel, ToolbarItems, DataStateChangeEventArgs, CommandModel, GridComponent} from '@syncfusion/ej2-angular-grids';
import { Observable } from 'rxjs/Observable';


@Component({
selector: 'app-emp',
templateUrl: './emp.component.html',
styles: [`./emp.component.css`],
providers: [SharedempService]
})

export class EmpComponent implements OnInit {
@ViewChild('grid')
public grid: GridComponent;
public editSettings: EditSettingsModel;
public toolbar: ToolbarItems[];
public pageSettings: Object;

reactForm: FormGroup;
constructor(private http: HttpClient, public service:SharedempService){
this.reactForm = new FormGroup({
'EmployeeId': new FormControl('', [FormValidators.required]),
'EmployeeName': new FormControl(''),
'Department': new FormControl(''),
'DateOfBirth': new FormControl(''),
'PhotoFileName': new FormControl(''),
});
}

public data: DataManager = new DataManager({
url: 'http://localhost:5000/api/',
adaptor: new WebApiAdaptor,
crossDomain: true
});

public fields: Object = { text: 'DepartmentName', value: 'DepartmentName' };
public query: Query = new Query().from('Department').select(['DepartmentName']).take(6);
public text: string = "Select a Department";

public ngOnInit(): void {

this.editSettings = {
allowEditing: true,
allowAdding: true,
allowDeleting: true,
showDeleteConfirmDialog: true,
mode: 'Dialog',
};
this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const state: any = { skip: 0, take: 12 };
this.service.execute(state);

let formId: HTMLElement = <HTMLElement>document.getElementById('formId');
document.getElementById('formId').addEventListener(
'submit',
(e: Event) => {
e.preventDefault();
if (this.reactForm.valid) {
alert('Customer details added!');
this.reactForm.reset();
} else {
// validating whole form
Object.keys(this.reactForm.controls).forEach(field => {
const control = this.reactForm.get(field);
control.markAsTouched({ onlySelf: true });
});
}
});
}

getRowData(args:any):void{
console.log(this.grid.getRowInfo(args.target));
}

onSubmit(form: NgForm){
this.service.postEmodel().subscribe(
res =>{
},
err =>{console.log(err); }
);
}

get check() { return this.reactForm.get('check'); }
get EmployeeId() { return this.reactForm.get('EmployeeId'); }
get EmployeeName() { return this.reactForm.get('EmployeeName'); }
get Department() { return this.reactForm.get('Department'); }
get DateOfBirth() { return this.reactForm.get('DateOfBirth'); }
get PhotoFileName() { return this.reactForm.get('PhotoFileName'); }


}



<div class="col-lg-12 control-section">
<div class="control_wrapper" id="control_wrapper" style="margin: 25px auto;">
<div class="formtitle">
<span>Add Employee Detailsspan>
div>

<form id="formId" [formGroup]="reactForm" #form="ngForm" (submit)="onSubmit(form)" class="form-horizontal" novalidate="">

<div class="form-group">
<div class="e-float-input">
<input id="EmployeeId" type="EmployeeId" formControlName="EmployeeId" [(ngModel)]="service.formData.EmployeeId">
<span class="e-float-line">span>
<label for="EmployeeId" class="e-float-text">EmployeeIdlabel>
div>
div>

<div class="form-group">
<div class="e-float-input">
<input id="EmployeeName" type="text" formControlName="EmployeeName" [(ngModel)]="service.formData.EmployeeName">
<span class="e-float-line">span>
<label for="EmployeeName" class="e-float-text">Employee Namelabel>
div>
div>

<div class="form-group">
<div class="e-float-input">
<ejs-dropdownlist id="Department" name="Department" formControlName="Department" [dataSource]='data' [fields]='fields' [placeholder]='text' [query]='query'
[(ngModel)]="service.formData.Department" floatLabelType='auto'>ejs-dropdownlist>
<span class="e-float-line">span>
div>
div>

<div class="form-group">
<div class="e-float-input">
<ejs-datepicker id="DateOfBirth" type="date" formControlName="DateOfBirth" placeholder="dob" [(ngModel)]="service.formData.DateOfBirth"
floatLabelType='auto'>ejs-datepicker>
<span class="e-float-line">span>
div>
div>

<div class="form-group">
<div class="e-float-input">
<input id="PhotoFileName" type="text" formControlName="PhotoFileName" [(ngModel)]="service.formData.PhotoFileName">
<span class="e-float-line">span>
<label class="e-float-text" for="PhotoFileName">photolabel>
div>
div>
<div class="row">
<div style="width: 320px;margin:0px auto;height: 100px;padding-top: 25px;">
<div style="display: inline-block;">
<button id="validateSubmit" class="samplebtn e-control e-btn e-primary" type="submit" style="height:40px;width: 150px;" >Add Employeebutton>
div>
<div style="float: right;">
<button id="resetbtn" class="samplebtn e-control e-btn" type="reset" style="height:40px;width: 150px;" data-ripple="true">Clearbutton>
div>
div>
div>
form>
div>
div>


<div>
<ejs-grid [dataSource]='service | async'
[toolbar]="toolbar"
[editSettings]="editSettings"
allowPaging= 'true'
[pageSettings]='pageSettings'
allowSorting= 'true'
allowGrouping= 'true'>
<e-columns>
<e-column field="EmployeeId" headerText="Employee ID" width="50" [visible]="false" [isPrimaryKey]="true"> e-column>
<e-column headerText="Employee Name" width="100">
<ng-template #template let-service>
<button (click)='getRowData($event)'>Editbutton>
ng-template>
e-column>
<e-column field="Department" headerText="Department" width="100"> e-column>
<e-column field="DateOfBirth" headerText="Date Of Birth" width="70"> e-column>
<e-column field="PhotoFileName" headerText="Photo" width="90"> e-column>
e-columns>
ejs-grid>
div>




import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { EmpModel } from './emp-model.model';
import { DataStateChangeEventArgs } from '@syncfusion/ej2-grids';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';


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

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

formData:EmpModel = new EmpModel();
list:EmpModel[];
readonly baseurl = 'http://localhost:5000/api/Emp'

postEmodel(){
return this.http.post(this.baseurl, this.formData);
}

refreshList(){
this.http.get(this.baseurl)
.toPromise()
.then(res => this.list = res as EmpModel[]);
}

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

getData( state ?: any): Observable<any[]> {
return this.http.get<EmpModel[]>(this.baseurl)
.map((response: any) => ({
// here we have return the result based on the skip and take count
result: state.take > 0 ? response.slice(state.skip, state.skip+state.take) : response,
count: response.length
} as any))
.map((data: any) => data);
}
}











PS Pavithra Subramaniyam Syncfusion Team May 24, 2022 08:56 AM UTC

Hi Charles,


You can achieve your requirement by using our Reactive forms Dialog template editing feature which helps to create the FormGroup with FormControls for each columns while editing. Please refer to the below demo and documentation link for more information as we suggested.


Demo   : https://ej2.syncfusion.com/angular/documentation/grid/editing/template-editing/#reactive-forms


                https://ej2.syncfusion.com/angular/demos/#/material/grid/dialog-reactive-form


If this doesn’t meet your requirement, please share the below details that will be helpful for us to provide a better solution as early as possible?


  1. What is the issue you are facing with the Dialog template feature?
  2. If you still want to use custom component, then please share a working sample for how you have tried to call the external form


Regards,

Pavithra S



CH Charles May 25, 2022 07:23 AM UTC

Hi Pavithra

I have resort to use the Hierarchy grid. The parent grid is loading but the child grid is not populating data from the server. I'm using observable method. below is my codes. Kindly assist

I intend to add more child grid such as Academic, Work experience, Next-of-kin etc. It is possible using the hierarchy grid?

import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { DataStateChangeEventArgs, DetailRowService } from '@syncfusion/ej2-angular-grids';
import { Observable } from 'rxjs/Observable';
import { SharedServiceService } from './shared-service.service';
import { NokserviceService } from './nokservice.service';


@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [DetailRowService]
})
export class AppComponent implements OnInit {
public data: Observable<DataStateChangeEventArgs>;
public childGrid:any;
public data1: Observable<DataStateChangeEventArgs>;
public state: DataStateChangeEventArgs;

constructor(public service:SharedServiceService, public service1:NokserviceService){
this.data = service;
this.data1 = service1;
}

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

ngOnInit(): void {
const state: any = { skip: 0, take: 12 };
this.service.execute(state);

this.childGrid = {
dataSource: this.data1 ,
queryString: 'EmployeeId',
columns: [
{ field: 'EmployeeId', headerText: 'ID', width: 50 },
{ field: 'Prefix', headerText: 'Prefix', width: 70 },
{ field: 'FirstName', headerText: 'FirstName', width: 80 },
{ field: 'OtherName', headerText: 'OtherName', width: 80 },
{ field: 'Relationship', headerText: 'Relationship', width: 80 },
{ field: 'Occupation', headerText: 'Occupation', width: 80 },
{ field: 'Address', headerText: 'Address', width: 100 },
{ field: 'Phone', headerText: 'Phone', width: 70 },
{ field: 'Email', headerText: 'Email', width: 80 }
]
};
}
}




<div class="control-section">
<ejs-grid #Grid id='Grid' [dataSource]='data | async' [childGrid]='childGrid'>
<e-columns>
<e-column field='EmployeeId' headerText='Employee ID' width='120' textAlign='Right'>e-column>
<e-column field='EmployeetName' headerText='Name' width='140'>e-column>
<e-column field='Department' headerText='Department' width='170'>e-column>
<e-column field='DateOfBirth' headerText='Date' width='120' format='yMd' textAlign='Right'>e-column>
<e-column field='PhotoFileName' headerText='Photo' width='120' textAlign='Right'>e-column>
e-columns>
ejs-grid>
div>



PS Pavithra Subramaniyam Syncfusion Team May 25, 2022 02:06 PM UTC

Hi Charles,


Query#1: I have resort to use the Hierarchy grid. The parent grid is loading but the child grid is not populating data from the server. I'm using observable method. below is my codes. Kindly assist


Due to some complexities, we could not set the observable binding to the child grid. However, you can fetch all the data using the service at initial rendering and set it to the child Grid. So the child Grid will perform the data actions locally. Please refer to the below code example and sample link for more information.


export class AppComponent {

  .   .  .

 

  public ngOnInit(): void {

    

    this.service2.getData().subscribe((x) => {

      this.grid.childGrid = {

        dataSource: x.result,

        queryString: 'EmployeeID',

        allowPaging: true,

        pageSettings: { pageSize: 6, pageCount: 5 },

        columns: [

          {

            field: 'EmployeeID',

            headerText: 'Employee ID',

            textAlign: 'Right',

            width: 120,

          },

          { field: 'FirstName', headerText: 'First Name', width: 120 },

          { field: 'LastName', headerText: 'Last Name', width: 120 },

        ],

      };

      this.grid.refreshHeader();

    });

  }

}

 

 


https://stackblitz.com/edit/angular-wtje1r?file=app%2Fapp.module.ts,app.component.html,app.component.ts,employee.service.ts,order.service.ts


Query#2: I intend to add more child grid such as Academic, Work experience, Next-of-kin etc. It is possible using the hierarchy grid?


If you want to add multilevel child grids, then you can set the childGrid property in a hierarchy manner. Please refer to the below demo which has 2 levels of the child.


https://ej2.syncfusion.com/angular/demos/#/material/grid/hierarchy


Or if you want to shoe multiple grids in the same level, then you can use the detail sample feature where you can render multiple Grids while expanding the parent row. Please refer to the below documentation and sample link for more information.


https://ej2.syncfusion.com/angular/documentation/grid/row/detail-template/

https://ej2.syncfusion.com/angular/demos/#/material/grid/detail-template


Regards,

Pavithra S



CH Charles May 26, 2022 10:09 PM UTC

Hi Pavithra,

In response to the solutions that you have provided, I want to create four child grid and not a multilevel one. Just one parent grid and for child grid.

I have tired other examples found on hierarchy grid documentations but was not successful. l wonder why It is only local binding of the hierarchy grid that seems to work. So l have also tried using the Data Manager to bind the hierarchy grid system but the child grid is still not loading data from the server. It shows only the column header text but no data from the server. Below is my codes;


import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { DetailRowService, EditSettingsModel, ToolbarItems } from '@syncfusion/ej2-angular-grids';
import { DataManager, Query, ReturnOption, UrlAdaptor } from '@syncfusion/ej2-data';

const SERVICE_URI = 'http://localhost:5000/api/Emp';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [DetailRowService]
})
export class AppComponent implements OnInit {

public gridData;
public dataManager;
public childGrid: any;
public data: object[] = [];
constructor(){
}

ngOnInit(): void {
new DataManager({ url: SERVICE_URI }).executeQuery(new Query().take(6)).then((e: ReturnOption) => {
this.data = e.result as object[];
}).catch((e) => true);

this.childGrid = {
dataSource: new DataManager({
url: "http://localhost:5000/api/nok",
adaptor: new UrlAdaptor()
}),
queryString: "EmployeeId",
actionBegin : function (args) {
},
columns: [
{ field: 'EmployeeId', headerText: 'ID', width: 50 },
{ field: 'Prefix', headerText: 'Prefix', width: 70 },
{ field: 'FirstName', headerText: 'FirstName', width: 80 },
{ field: 'OtherName', headerText: 'OtherName', width: 80 },
{ field: 'Relationship', headerText: 'Relationship', width: 80 },
{ field: 'Occupation', headerText: 'Occupation', width: 80 },
{ field: 'Address', headerText: 'Address', width: 100 },
{ field: 'Phone', headerText: 'Phone', width: 70 },
{ field: 'Email', headerText: 'Email', width: 80 },
]
}

}
}


PS Pavithra Subramaniyam Syncfusion Team May 27, 2022 02:21 PM UTC

Hi Charles,


Query#1: I want to create four child grid and not a multilevel one. Just one parent grid and for child grid.


We suggest the Detail template feature to achieve your requirement which provides an option to render custom components for each parent row. Please refer to the below code example and documentation link for more information.


<div class="control-section">

  <ejs-grid #grid [dataSource]='data' id='Grid'>

    <ng-template #detailTemplate let-data>

      <div style="display:inline-block">

        <ejs-grid id='ChildGrid1' [dataSource]='childData1' [allowPaging]="true" width="49%">

          <e-columns>

          .  .  .

            </e-column>

          </e-columns>

        </ejs-grid>

        <ejs-grid id='ChildGrid2' [dataSource]='childData2' [allowPaging]="true" width="49%">

          <e-columns>

          .  .  .

          </e-columns>

        </ejs-grid>

      </div>

    </ng-template>

    <e-columns>

      <e-column field='EmployeeID' headerText='Employee ID' width='125' textAlign='Right'></e-column>

      .  .  .

    </e-columns>

 

  </ejs-grid>

</div>

 


Documentation: https://ej2.syncfusion.com/angular/documentation/grid/row/detail-template/


Query#2: l have also tried using the Data Manager to bind the hierarchy grid system but the child grid is still not loading data from the server.


It shows only the column header text but no data from the server


The child Grid data is binding fine with DataManager at our end. So if you want to still use the Hierarchy Grid instead of Details template to achieve your requirement please share an issue reproducible sample that will be helpful for us to provide a better solution.


Regards,

Pavithra S



CH Charles May 31, 2022 01:43 PM UTC

Hi Pavithra,

The codes you have provided does not meet my requirement. I think the Hierarchy grid is what l want to use. My parent grid is Employee grid and the child is next-of-kin (nok) grid. So l want to bind the parent and child grid with a unique EmployeeID. When l select an employee then it should display the next-of-kin record in child grid for that particular Employee.

Parent grid- Employee ID: 001 EmployeeName: David Oher Department: Account and records

child grid- Employee ID: 001 FirstName: Linda OtherName: Oher Relationship: Sister

The link below is what l have tried

https://stackblitz.com/edit/angular-kqu7vy-rwnq62?file=app.component.ts,app.component.html



PS Pavithra Subramaniyam Syncfusion Team June 1, 2022 03:20 PM UTC

Hi Charles,


In your sample, we could see that you want to set the Grid with local data binding. So, we suggest you set the “offline” property as true and set an appropriate Adaptor. In your case it seems that you are using an API endpoint, so we suggest our WebApiAdaptor. Please refer to the below code example and sample link for more information.


this.data = new DataManager({

  url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Employees/',

  adaptor: new ODataV4Adaptor(),

  offline: true,

}, new Query().take(6));

 

this.childGrid = {

  dataSource: new DataManager(

    {

      url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/',

      adaptor: new ODataV4Adaptor(),

      offline: true,

    },

    new Query().take(6)

  ),

  queryString: 'EmployeeID',

  columns: [

    { field: 'EmployeeID', headerText: 'ID', width: 50 },

    { field: 'CustomerID', headerText: 'FirstName', width: 80 },

  ],

};

 


Sample: https://stackblitz.com/edit/angular-kqu7vy-wyokne?file=app.component.ts,app.component.html


Regards,

Pavithra S



CH Charles June 2, 2022 09:50 AM UTC

Hi Pavithra

Your solution have work, thank you.

I tried to add a second and third child but it didn't work. I want it like in the below structure if possible

ParentGrid(Employee list)

childGrid1(next-of-kin), childGrid2(Academic), childGrid3(Work experience).

Thank you



PS Pavithra Subramaniyam Syncfusion Team June 3, 2022 01:49 PM UTC

Hi Charles,


By default, using the Hierarchy Binding feature we could not render multiple child Grid at the same level. So, we are afraid that your requirement is not feasible with the current architecture.


Please get back to us if you need further assistance.


Regards,

Pavithra S



CH Charles June 8, 2022 06:38 AM UTC

Hi Pavithrw,

Thank you for the clarification of hierarchy grid. What about the master/detail relationship grid? Does it renders multiple detail grid at the same level?

You also provided the option of parent grid and multiple child grid. How would l link EmployeeID in the parent grid to the multiple child/detail grid in the codes below?

<div class="control-section">

  <ejs-grid #grid [dataSource]='data' id='Grid'>

    <ng-template #detailTemplate let-data>

      <div style="display:inline-block">

        <ejs-grid id='ChildGrid1' [dataSource]='childData1' [allowPaging]="true" width="49%">

          <e-columns>

          .  .  .

            </e-column>

          </e-columns>

        </ejs-grid>

        <ejs-grid id='ChildGrid2' [dataSource]='childData2' [allowPaging]="true" width="49%">

          <e-columns>

          .  .  .

          </e-columns>

        </ejs-grid>

      </div>

    </ng-template>

    <e-columns>

      <e-column field='EmployeeID' headerText='Employee ID' width='125' textAlign='Right'></e-column>

      .  .  .

    </e-columns>

 

  </ejs-grid>

</div>




PS Pavithra Subramaniyam Syncfusion Team June 8, 2022 12:17 PM UTC

Hi Charles,


You can achieve your requirement with the Detail Template feature by passing the corresponding parent key to the child Grid filter query. Please refer to the below code example and sample link for more information.


 

@Component({

  selector: 'app-root',

  templateUrl: `<ejs-grid #grid [dataSource]="data" id="Grid">

    <ng-template #detailTemplate let-data>

      <div style="display:inline-block">

        <div style="float:left;width:49%;">

          <h1>ChildGrid1</h1>

          <ejs-grid id="ChildGrid1" [dataSource]="childData1" [query]="getQuery(data.EmployeeID)"

            [columns]="columns1" [allowPaging]="true" [pageSettings]="pageSettings">

          </ejs-grid>

        </div>

        <div style="float:right;width:49%;">

          <h1>ChildGrid2</h1>

          <ejs-grid id="ChildGrid2" [dataSource]="childData2" [query]="getQuery(data.EmployeeID)"

             [columns]="columns2" [allowPaging]="true" [pageSettings]="pageSettings">

          </ejs-grid>

        </div>

      </div>

    </ng-template>

    <e-columns>

      .  .   .

    </e-columns>

  </ejs-grid>`,

})

export class AppComponent {

  

  .  .  .

 

  public getQuery(value: Date): Query {

    return new Query().where('EmployeeID''equal', value);

  }

}

 

 


Sample: https://stackblitz.com/edit/angular-zrusab?file=app.component.html,app.component.ts,data.ts


Please get back to us if you need further assistance on this.


Regards,

Pavithra S



CH Charles June 24, 2022 11:51 AM UTC

Hi Pavithra,


In this project all is working fine except that image is not uploaded to the destination folder. As soon as l click on the submit button l want image to be uploaded into a folder path. I don't know how to pass the upload action to submit button method. Kindly assist


https://stackblitz.com/edit/angular-kqu7vy-8xkfis?file=app.component.ts,emp.service.ts



CH Charles June 24, 2022 02:07 PM UTC

Hi Pavithra,

My grid is not showing image from the destination folder. Kindly assist


https://stackblitz.com/edit/angular-nqk33p?file=order.service.ts



PS Pavithra Subramaniyam Syncfusion Team June 24, 2022 02:16 PM UTC

Hi Charles,


We tried to run the shared samples but got the below errors.


Sample: https://stackblitz.com/edit/angular-nqk33p?file=order.service.ts



Sample: https://stackblitz.com/edit/angular-kqu7vy-8xkfis?file=app.component.ts



So could you please share workable samples and share the screenshot of your issues for better understanding.


Regards,

Pavithra S



CH Charles June 24, 2022 11:43 PM UTC

Hi Pavithra,

  1. You can not check the two links to see what l have tried in my most recent post. The below image showed that Employee image is not showing from the folder 'Photos' at the backend. 

  grid image not showing.png 

2.  The second file shows the destination path folder where Employee Image are uploader to.


destination.png


Kindly assist.



PS Pavithra Subramaniyam Syncfusion Team June 27, 2022 01:25 PM UTC

Hi Charles,


Thanks for your update.


From your code, it seems that you are trying to upload images through the EJ2 uploader inside a local folder and display it in the Grid. To validate this scenario please share the below details that will be helpful for us to provide a better solution.


  1. Share the controller code for saving the images to the local folder
  2. Are you uploading the images using an EJ2 uploader outside the Grid or Grid Edit dialog?
  3. Is there any script error?


Regards,

Pavithra S



CH Charles replied to Pavithra Subramaniyam June 28, 2022 10:00 PM UTC

Hi Pivithra,

Yes i'm loading image into a local folder which is working fine. My aim to assign the uploader code to the 'Submit' button so that as soon as l click on submit it would the save the image into the folder while the other data including the image name (text) will be save into the database via web API. This is working fine when I turn the auto upload to true, but it did upload selected image into it destination folder even when l have not click on submit. So i want all action to be done at once.

see link below:

https://stackblitz.com/edit/angular-nqk33p?file=main.ts


Second question is grid is not showing image from the folder even when there are many images in it. Below is my codes and link

https://stackblitz.com/edit/angular-kqu7vy-8xkfis?file=app.component.ts


using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Data;
using WebApplication1.Models;
using Microsoft.Extensions.Configuration;
using System.Net.Http;
using System.IO;
using Microsoft.Extensions.FileProviders;
using Microsoft.AspNetCore.Hosting;

namespace WebApplication1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class emp3Controller : ControllerBase
    {
        private readonly IConfiguration _configuration;
        private readonly IWebHostEnvironment _env;

        public emp3Controller(IConfiguration configuration, IWebHostEnvironment env)
        {
            _configuration = configuration;
            _env = env;
        }

        [HttpGet]

        public JsonResult Get()
        {
            string query = @"select EmployeeID, EmployeeName, Department,
            Convert(varchar(10),DateOfBirth,120) as DateOfBirth,
            PhotoFileName from dbo.emp3";
            DataTable dt = new DataTable();
            string sqlDataSource = _configuration.GetConnectionString("EmployeeAppCon");
            SqlDataReader dr;
            using (SqlConnection con = new SqlConnection(sqlDataSource))
            {
                con.Open();
                using (SqlCommand cmd = new SqlCommand(query, con))
                {
                    dr = cmd.ExecuteReader();
                    dt.Load(dr);
                    dr.Close();
                    con.Close();
                }
            }

            return new JsonResult(dt);
        }

        [HttpPost]
        public JsonResult Post(Emp emp)
        {
            string query = @"insert into dbo.emp3 (EmployeeName, Department, DateOfBirth, PhotoFileName) values
            ('" + emp.EmployeeName + @"','" + emp.Department + @"','" + emp.DateOfBirth + @"','" + emp.PhotoFileName + @"')";
            DataTable dt = new DataTable();
            string sqlDataSource = _configuration.GetConnectionString("EmployeeAppCon");
            SqlDataReader dr;
            using (SqlConnection con = new SqlConnection(sqlDataSource))
            {
                con.Open();
                using (SqlCommand cmd = new SqlCommand(query, con))
                {
                    dr = cmd.ExecuteReader();
                    dt.Load(dr);
                    dr.Close();
                    con.Close();
                }
            }

            return new JsonResult("Added Successfully");
        }

        [HttpPut]
        public JsonResult Put(Emp emp)
        {
            string query = @"
                update dbo.emp3 set EmployeeName = '" + emp.EmployeeName + @"', Department =  '" + emp.Department + @"',
                DateOfBirth = '" + emp.DateOfBirth + @"', PhotoFileName = '" + emp.PhotoFileName + @"'
                where EmployeeID = " + emp.EmployeeID + @"
                    ";
            DataTable dt = new DataTable();
            string sqlDataSource = _configuration.GetConnectionString("EmployeeAppCon");
            SqlDataReader dr;
            using (SqlConnection con = new SqlConnection(sqlDataSource))
            {
                con.Open();
                using (SqlCommand cmd = new SqlCommand(query, con))
                {
                    dr = cmd.ExecuteReader();
                    dt.Load(dr);
                    dr.Close();
                    con.Close();
                }
            }

            return new JsonResult("Updated Successfully");
        }

        [HttpDelete("{id}")]
        public JsonResult Delete(int id)
        {
            string query = @"
                    delete from dbo.emp3
                    where EmployeeID = " + id + @"
                    ";
            DataTable dt = new DataTable();
            string sqlDataSource = _configuration.GetConnectionString("EmployeeAppCon");
            SqlDataReader dr;
            using (SqlConnection con = new SqlConnection(sqlDataSource))
            {
                con.Open();
                using (SqlCommand cmd = new SqlCommand(query, con))
                {
                    dr = cmd.ExecuteReader();
                    dt.Load(dr);
                    dr.Close();
                    con.Close();
                }
            }

            return new JsonResult("Deleted Successfully");
        }

        [Route("SaveFile")]
        [HttpPost]
        public JsonResult SaveFile()
        {
            try
            {
                var httpRequest = Request.Form;
                var postedFile = httpRequest.Files[0];
                string filename = postedFile.FileName;
                var physicalPath = _env.ContentRootPath + "/Photos/" + filename;

                using (var stream = new FileStream(physicalPath, FileMode.Create))
                {
                    postedFile.CopyTo(stream);
                }

                return new JsonResult(filename);
            }
            catch (Exception)
            {
                return new JsonResult("anonymous.png");
            }
        }

       
    }
}



PS Pavithra Subramaniyam Syncfusion Team June 29, 2022 12:44 PM UTC

Hi Charles,


Thanks for the details.


Query#1: My aim to assign the uploader code to the 'Submit' button so that as soon as l click on submit it would the save the image into the folder


From your query, we understood that you want to upload the files while clicking the submit button of the form. You can achieve your requirement by calling the “upload” method of the EJ2 uploader component inside the submit button click event which will upload the selected files (added to the upload queue).


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


Query#2: is grid is not showing image from the folder even when there are many images in it.


From the shared code and images, we suspect that the url given to the Grid column template must be not matched to the original folder in your sample. Could you please ensure whether the given url is correct (“http://localhost:5000/Photos{{ data.EmployeeID }}.png”) at your end? If yes, please share the script error and the path of any of your locally stored images for further validation.


Regards,

Pavithra S



CH Charles June 30, 2022 09:04 PM UTC

Hi Pavithra,


Script Error:

GET http://localhost:5000/Photos/passportn.jpg 404 (Not Found)


Path of my stored image

C:\Users\don\Desktop\projectA\API core\WebApplication1\Photos\passportn.jpg


Just in case this didn't work, I will appreciate it if you can provide me with a working codes l can use to load my grid from my stored image folder.





PS Pavithra Subramaniyam Syncfusion Team July 1, 2022 12:34 PM UTC

Hi Charles,


Currently, we are preparing a working sample for displaying images in Grid from the local folder and we will share the sample on July 04th, 2022. Until then we appreciate your patience.


Regards,

Pavithra S



CH Charles July 5, 2022 07:58 AM UTC

Hi Pavithra,

I'm yet to get the working sample for displaying images in Grid from the local folder as promised by you on 4th of July 2022.

RegardsC

Charles



PS Pavithra Subramaniyam Syncfusion Team July 5, 2022 02:19 PM UTC

Hi Charles,


Thanks for your patience.


We have prepared a sample in which we have displayed the images from the local folder using Grid column template. Please refer to the attached sample in which we have added a folder “Photos” inside the “wwwroot” and added the images which are shown inside the Grid column.



Regards,

Pavithra S


Attachment: NgCoreGridImage_b3a6535f.zip


CH Charles July 12, 2022 06:28 PM UTC

Hi Pavithra,

I was able to successfully replicate your sample by populating local data, but l could not accomplished it via data from the server as it displayed only the first row on the grid even as l have many records in the database. Kindly assist

https://stackblitz.com/edit/angular-nqk33p-5tyqds?file=app.component.ts,app.component.html







PS Pavithra Subramaniyam Syncfusion Team July 13, 2022 09:32 AM UTC

Hi Charles,


We have tried to reproduce the issue with the given code, but it is working fine at our end with the proper image URL. Please refer to the below screenshot for more information.




So could you please share an issue reproducible sample with a real API link instead of stack blitz or try to reproduce the issue in our previously shared sample and share it with us which will be helpful for us to validate further since it seems like an environmental issue only occurs in your sample.


Regards,

Pavithra S



CH Charles July 17, 2022 10:05 PM UTC

Hi Pavithra,

From the sample you provided it loads the grid with its local data but l don't know how to connect to the database. I want to populate my grid with data from the database. Using the Northwind for example can you show me how to set datasource in Controller?

Regards



PS Pavithra Subramaniyam Syncfusion Team July 18, 2022 04:06 PM UTC

Hi Charles,


For binding data from the controller actions, you could use our EJ2 DataManager with an appropriate adaptor based on your server. Please refer to the below documentation for example code of remote data binding.


https://ej2.syncfusion.com/angular/documentation/grid/data-binding/remote-data/


If you are still facing the issue, please share the runnable sample with the issue as we requested earlier so that we could validate the issue and provide a better solution.


Regards,

Pavithra S



CH Charles July 18, 2022 09:23 PM UTC

Hi Pavithra,

I didn't find anything related to my issue from the link documentation that you provided. I mentioned in my most recent post that the sample you provided shows how to load grid from local data. But my problem is how to create the controller to enable database interaction. A controller must be created to as grid at the frontend (angular) will populate data from the database. To load data from the database there must be a connection string for example SqlConnection con = new SqlConnection(@"Data Source=DESKTOP-3HTYF;Initial Catalog=EmployeeDB;Integrated Security=True")


The codes below is from your sample project. Kindly assist me with connection to MSSQL database in it.


using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using Syncfusion.EJ2.Base;

using System;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;


namespace GridAngularCore.Controllers

{

    public class HomeController : Controller

    {

        // GET: HomeController

        public ActionResult Index()

        {

            return View();

        }


        // POST:

        [HttpPost]

        public IActionResult UrlDatasource([FromBody] DataManagerRequest dm)

        {

            IEnumerable DataSource = OrdersDetails.GetAllRecords();

            DataOperations operation = new DataOperations();

            if (dm.Search != null && dm.Search.Count > 0)

            {

                DataSource = operation.PerformSearching(DataSource, dm.Search);  //Search

            }

            if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting

            {

                DataSource = operation.PerformSorting(DataSource, dm.Sorted);

            }

            if (dm.Where != null && dm.Where.Count > 0) //Filtering

            {

                DataSource = operation.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);

            }

            List<string> str = new List<string>();

            if (dm.Aggregates != null)

            {

                for (var i = 0; i < dm.Aggregates.Count; i++)

                    str.Add(dm.Aggregates[i].Field);

            }

            IEnumerable aggregate = operation.PerformSelect(DataSource, str);

            int count = DataSource.Cast<object>().Count();

            if (dm.Skip != 0)

            {

                DataSource = operation.PerformSkip(DataSource, dm.Skip);   //Paging

            }

            if (dm.Take != 0)

            {

                DataSource = operation.PerformTake(DataSource, dm.Take);

            }

            return dm.RequiresCounts ? Json(new { result = DataSource, count = count, aggregate = aggregate }) : Json(DataSource);

        }

    }

    public class OrdersDetails

    {

        public static List<OrdersDetails> order = new List<OrdersDetails>();

        public OrdersDetails()

        {

        }

        public OrdersDetails(int OrderID, int EmployeeId, double Freight, DateTime OrderDate, string ShipCountry, string ShipID)

        {

            this.OrderID = OrderID;

            this.EmployeeID = EmployeeId;

            this.Freight = Freight;

            this.OrderDate = OrderDate;

            this.ShipCountry = ShipCountry;

            this.ShipID = ShipID;

        }

        public static List<OrdersDetails> GetAllRecords()

        {

            if (order.Count() == 0)

            {

                int code = 1;

                for (int i = 1; i < 2; i++)

                {

                    order.Add(new OrdersDetails(code + 1, i + 0, 2.3 * i, new DateTime(1991, 05, 15, 2, 32, 5), "Denmark", "1"));

                    order.Add(new OrdersDetails(code + 2, i + 1, 3.3 * i, new DateTime(1990, 04, 04), "USA", "2"));

                    order.Add(new OrdersDetails(code + 3, i + 2, 4.3 * i, new DateTime(1957, 11, 30), "Brail", "3"));

                    order.Add(new OrdersDetails(code + 4, i + 3, 5.3 * i, new DateTime(1930, 10, 22), "Austria", "4"));

                    order.Add(new OrdersDetails(code + 5, i + 4, 6.3 * i, new DateTime(1953, 02, 18), "Switzerland", "5"));

                    code += 5;

                }

            }

            return order;

        }

        public int? OrderID { get; set; }

        public int? EmployeeID { get; set; }

        public double? Freight { get; set; }

        public DateTime? OrderDate { get; set; }

        public string ShipCountry { get; set; }

        public string ShipID { get; set; }

    }

}





PS Pavithra Subramaniyam Syncfusion Team July 19, 2022 01:42 PM UTC

Hi Charles,


We have prepared a sample to connect the Northwind DB and fetch the data from the server using the “UrlAdaptor”. Please refer to the attached sample for more information.


Note: to bind the data source properly, kindly change the connectionstring of Northwnd.MDF file in the appsettings.json file.  

Regards,

Pavithra S


Attachment: GridDBNG_e375e693.zip


CH Charles July 28, 2022 11:45 PM UTC

Hi Pavithra,

The sample that you have provided is not working. I have been trying for few days without succeeding. I'm using Visual studio 2022 with angular version 12. I'll appreciate it if you could either recreate or provide any sample (connected to database) using Visual Studio 2022.

Regards Charles



PS Pavithra Subramaniyam Syncfusion Team August 1, 2022 11:03 AM UTC

Hi Charles,


We have prepared a new sample based on your update. Please refer to the attached sample for more information. If you still having any issues, please share the below details that will be helpful or us to provide a better solution as early as possible.


  1. Are you facing issues only when using Grid?
  2. Can you get the data with a simple ajax in your sample (without any Grid or DataManager)?
  3. Share the sample in which you are facing the Grid issue


Regards,

Pavithra S


Attachment: Grid_d4f6532c.zip


CH Charles August 14, 2022 08:30 PM UTC

Hi Pavithra,

When I select a row on the grid for editing the value of the dropdown list clears. I want the dropdown list to retain its original value when l select a row for editing. Kindly assist. See link attached below


https://stackblitz.com/edit/angular-kqu7vy-rmhdpx?file=app.component.ts,app.component.html


How can l change grid column header text to bold?



PS Pavithra Subramaniyam Syncfusion Team August 15, 2022 12:17 PM UTC

Hi Charles,


Query#1: When I select a row on the grid for editing the value of the dropdown list clears. I want the dropdown list to retain its original value when l select a row for editing.


To show the corresponding field value in the DropDownList component while editing, you need to set “value” or “text” property with the field value. Since you are returning the “this.segmentObj.text” inside the “read” function you need to set the “text” property to achieve your requirement. Please refer to the below code example and API link for more information.


write: (args) => {

  this.segmentObj = new DropDownList({

    dataSource: this.segment,

    fields: { value: 'segmentId', text: 'segmentName' },

    text: args.rowData[args.column.field],

    placeholder: 'Select a Segment',

    floatLabelType: 'Never',

  });

  this.segmentObj.appendTo(this.segmentElem);

},

    };

 


Query#2: How can l change grid column header text to bold?


You can set the “font-weigth” style to the header text by using the below style.


.e-grid span.e-headertext {

        font-weight: bold;

}

 


Please get back to us if you need further assistance.


Regards,

Pavithra S



CH Charles August 15, 2022 10:10 PM UTC

Hi Pavithra,

Thank you for the solution that you had provided. It works with local data binding, but l intend to connect the grid drop down with the server. So, I've tried the codes below but didn't work as expected. Can you show me how to load the grid drop down with data from the server?

write: (args) => {
this.dataObj = new DropDownList({
dataSource: new DataManager({ url: 'http://localhost:5000/api/Department' }).executeQuery(new Query().take(6)).then((e: ReturnOption) => {
this.data = e.result as object[]; }).catch((e) => true);
fields: { value: 'DepartmentId', text: 'DepartmentName' },
text: args.rowData[args.column.field],
placeholder: 'Select a dept',
floatLabelType: 'Never',
});
this.dataObj.appendTo(this.dataElem);
},



2.  I want to upload the files while clicking the submit button of the form.  

I have tried by calling the upload method of the EJ2 uploader component inside the submit button click event but it seems that i'm might not doing it wrong. Kindly assist

https://stackblitz.com/edit/angular-nqk33p?file=app.component.ts








PS Pavithra Subramaniyam Syncfusion Team August 16, 2022 02:24 PM UTC

Hi Charles,


Query#1: Can you show me how to load the grid drop down with data from the server?


You can set the dataSource from the server inside the “then” function as in the below code example.


write: (args) => {

  this.segmentObj = new DropDownList({

    fields: { value: 'ShipCountry', text: 'ShipCity' },

    text: args.rowData[args.column.field],

    placeholder: 'Select a Segment',

    floatLabelType: 'Never',

  });

  new DataManager({

    url: 'https://ej2services.syncfusion.com/production/web-services/api/Orders',

  })

    .executeQuery(new Query().take(6))

    .then((e: any) => {

      this.segmentObj.dataSource = e.result.result as object[];

      this.segmentObj.appendTo(this.segmentElem);

    });

},

    };

 


Query#2:I want to upload the files while clicking the submit button of the form. 


We have created a new forum under your account regarding the EJ2 Uploader component. Please follow that for more updates.


Note: Please create a new forum for new queries for a better follow-up in the future.


Regards,

Pavithra S



CH Charles replied to Pavithra Subramaniyam August 16, 2022 07:12 PM UTC

Hi Pavithra,

The codes that you provided didn't work. The error is found on this line this.segmentObj.dataSource = e.result.result as object[];



PS Pavithra Subramaniyam Syncfusion Team August 17, 2022 01:58 PM UTC

Hi Charles,


To overcome the reported issue, we suggest checking the result from the API call inside the “then” function and based on the result value set the dataSource property for the DropDownList.


 

// check the response “e” here and if e.result contains the records then set it to the ‘dataSource’

// setting “e.result” is given as an example purpose only. You can change the below line base on your API response

 

this.segmentObj.dataSource = e.result as object[];

 



Regards,

Pavithra S



CH Charles August 17, 2022 08:35 PM UTC

Hi Pavithra,

I have tried everything that you had asked me to do but is still didn't work. I'll appreciate it if you can get me any other options of loading grid's dropdownList with data from the server.

Regards

Charles



PS Pavithra Subramaniyam Syncfusion Team August 18, 2022 09:02 AM UTC

Hi Charles,


You can also use the EJ2 Adaptors to fetch data from the server. Please refer to the below code example and documentation link for more information.


this.segmentObj = new DropDownList({

  dataSource: new DataManager({

    url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders',

    adaptor: new ODataV4Adaptor(),

    crossDomain: true,

  }),

  query: new Query().take(6),

  fields: { value: 'CustomerID', text: 'CustomerID' },

  text: args.rowData[args.column.field],

  placeholder: 'Select a Segment',

  floatLabelType: 'Never',

});

this.segmentObj.appendTo(this.segmentElem);

 


Documentation: https://ej2.syncfusion.com/angular/documentation/data/adaptors/#web-api-adaptor

  https://ej2.syncfusion.com/angular/documentation/drop-down-list/data-binding/#binding-remote-data


If you are still facing the issue, please share an issue reproducible sample with a simple API backend which will be helpful for us to validate the issue and provide a better solution as early as possible.


Regards,

Pavithra S



CH Charles August 18, 2022 11:46 AM UTC

Hi Pavithra,


Thank you for all your efforts towards helping me solve my problems. I have fixed the problem. All this while l didn't call [edit]='segmentParams' in my html component. That was the problem.


Regards

Charles




PS Pavithra Subramaniyam Syncfusion Team August 21, 2022 04:00 PM UTC

Hi Charles,


We are glad to hear that you have achieved your requirement! Please get back to us if you need further assistance on this.


Regards,

Pavithra S



CH Charles August 25, 2022 09:32 PM UTC

Hi Pavithra,

I'm having issue trying to load data from the database to drop down list. I have tried the codes below but was not successful. Kindly assist


prefixController

using Microsoft.AspNetCore.Mvc;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using Syncfusion.EJ2.Base;

using project11.Models;


namespace project11 .Controllers

{

public class prefixController : Controller

{

private readonly bhfdbContext _context;

public prefixController(bhfdbContext context)

{

_context = context;

}

public IActionResult Index()

{

return View();

}

public IActionResult Privacy()

{

return View();

}

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]


public IActionResult UrlDatasource([FromBody] DataManagerRequest dm)

{

IEnumerable DataSource = _context.Prefix.ToList();

int count = DataSource.Cast().Count();

return Json(new { result = DataSource, count = count });

}

}

}



app.component.ts

this.prefixParams = {

create: () => {

this.prefixElem = document.createElement('input');

return this.prefixElem;

},

read: () => {

return this.prefixObj.text;

},

destroy: () => {

this.prefixObj.destroy();

},

write: (args) => {

this.prefixObj = new DropDownList({

fields: { value: 'PrefixId', text: 'PrefixName' },

text: args.rowData[args.column.field],

placeholder: 'Select a title',

floatLabelType: 'Never',

});

new DataManager({

url: 'prefix/UrlDatasource', adaptor: new UrlAdaptor()

})

.executeQuery(new Query().take(6))

.then((e: any) => {

this.prefixObj.dataSource = e.result;

this.prefixObj.appendTo(this.prefixElem);

});

},

};





PS Pavithra Subramaniyam Syncfusion Team August 26, 2022 03:05 PM UTC

Hi Charles,


We have tried the same code you shared with us to reproduce the issue, but the DropDownList is loaded, and the editing is working fine. Please refer to the attached screenshot and sample for more information.



From your code, we suspect that the Database is not returning the data inside the “UrlDatasource” action. So, we suggest ensuring that the data is assigned properly in “DataSource” inside the “UrlDatasource” action. If you are still facing the issue, please share an issue reproducible sample with a working backend which will be helpful for us to validate the issue and provide a better solution as early as possible.


Regards,

Pavithra S


Attachment: GridDropDownEdit_c2e23dd8.zip


CH Charles August 28, 2022 11:50 PM UTC

Hi Pavithra,

My aim to to load drop down list with data from Prefix table in the database. I have two controllers is CustomerController and PrefixController with just a single grid control. The grid will load all data from the customet table in the database. The drop down edit in the grid is to load all data from Prefix table in the database. See attached file where l have modified your sample to imitate my scenario. Kindly assist




Attachment: GridDropDownEdit_8cfa4a5f.zip


PS Pavithra Subramaniyam Syncfusion Team August 29, 2022 02:01 PM UTC

Hi Charles,


Thanks for sharing the sample.


We have validated the sample and found that you are trying to fetch data using the “UrlAdaptor” from a Web API endpoint by defining normal action inside the “OrderControler”. This is the cause of the reported issue. If you want to fetch data from the API endpoint, we suggest the “WebApiAdaptor” which expected the server response as “Items” and “Counts” pair. Please refer to the below code example and screenshot for more information.


new DataManager({

                    url: 'api/Order', adaptor: new WebApiAdaptor()

                })

                    .executeQuery(new Query().take(6))

                    .then((e: any) => {

                        this.prefixObj.dataSource = e.result;

                        this.prefixObj.appendTo(this.prefixElem);

                    });


// GET: api/Orders

        [HttpGet]

 

        public object Get()

        {

            var data = OrdersDetails.GetAllRecords();            

            return new { Items = data, Count = data.Count() };

 

        }



If you are still facing the issue, please ensure the below scenarios to validate the issue based on which we can suggest a suitable adaptor to achieve your requirement.


  1. Ensure whether the dropdown list data can be fetched by using the JavaScript ajax instead of using our DataManager
  2. If yes, what type of request the endpoint accepts (POST or GET)?
  3. Share the response screenshot from the server while fetching the data from the ajax call
  4. If you don’t need any server-side action dynamically with the dropdown data source then, you can simply set the “this.prefixObj.dataSource” inside the ajax success function and call the “appendTo” method.


Regards,

Pavithra S




CH Charles August 29, 2022 10:43 PM UTC

Hi pavithra,

I'm not using Web api endpoint. I'm using the normal action to populated my grid from the database which works fine. The drop down is not showing data from the base. I use the example you provided past week but is still not work.

Regards 

Charles



PS Pavithra Subramaniyam Syncfusion Team August 30, 2022 06:53 AM UTC

Hi Charles,


As we requested in our previous update, please share the below details that will be helpful for us to provide a better solution as early as possible.


  1. Ensure whether the required data can be fetched by using the JavaScript ajax instead of using our DataManager like  the below page

https://www.geeksforgeeks.org/how-to-make-ajax-call-from-javascript/

  1. Share the response screenshot from the server while fetching the data from the ajax call
  2. If you don’t need any server-side action dynamically with the dropdown data source then, try to set the “this.prefixObj.dataSource” inside the ajax success function.


Regards,

Pavithra S



CH Charles September 14, 2022 10:27 PM UTC

Hi Pavithra,

I have explored so many of your documentations on drop down but couldn't find a suitable help for this problem. I have a drop down and a textbox. The drop down is bind to a datasource, so when l select an item from drop down the textbox should be populated with its corresponding value from the database. For example 

Drop down                Textbox

EmployeeId                Firstname                  

001                              Mark                          

002                              Mary                          

003                              Sabina                       

So, when l select EmployeeId ‘002’ from the drop down then ‘Mary’ would be displayed in the textbox. Kindly assist



export class EmployeeComponent implements OnInit {

 

  reactForm: FormGroup;

  public textboxValue;

  public height: string = '250px';

 

  constructor(public service: employeeService, private formBuilder: FormBuilder) { }

 

  ngOnInit() {

    this.textboxValue='';

    this.reactForm = new FormGroup({

      'EmployeeId': new FormControl('', [FormValidators.required]),     

      'FirstName': new FormControl('', [FormValidators.required])     

    });   

 

       let formId: HTMLElement = <HTMLElement>document.getElementById('formId');

    document.getElementById('formId').addEventListener(

      'submit',

      (e: Event) => {

        e.preventDefault();

        if (this.reactForm.valid) {         

          this.service.postemployee(this.reactForm.value).subscribe(

            res=>{ 

              this.reactForm.reset();           

             },

             err => { console.log(err);}

           )             

        } else {

          // validating whole form

          Object.keys(this.reactForm.controls).forEach(field => {

            const control = this.reactForm.get(field);

            control.markAsTouched({ onlySelf: true });

          });

        }

      });

  } 

 

  public data: DataManager = new DataManager({

      url: 'api/Employees',

      adaptor: new WebApiAdaptor()     

  });

 

  public fields: Object = { text: 'FirstName', value: 'FirstName' };

  public query: Query = new Query().from('Employees').select(['FirstName']).take(6);;

  public WaterMark: string = "Select a name";

 

 

  get EmployeeId() { return this.reactForm.get('EmployeeId'); } 

  get FirstName() { return this.reactForm.get('FirstName'); }

 

}

 




<div class="formtitle">

            <span>Add Next-of-kin Details</span>

        </div>

        <form id="formId" [formGroup]="reactForm" #formDir="ngForm" class="form-horizontal" novalidate="">

            <div class="form-row">

                <div class="form-group col">

                    <div class="e-float-input" id='content' style="margin: 0px auto; width:300px; padding-top: 20px;">                       

                        <ejs-dropdownlist [dataSource]='data' [(value)]='value' id="employees" type="text" formControlName="EmployeeId" [fields]='fields'

                                          [query]='query' [popupHeight]='height' sortOrder='Ascending'>                           

                        </ejs-dropdownlist>

                        <span class="e-float-line"></span>

                        <label class="e-float-text">Employee ID</label>

                    </div>

                    <div *ngIf="EmployeeId.errors">

                        <div *ngIf="EmployeeId.errors.required && EmployeeId.touched" class="e-error">

                            This field is required.

                        </div>

                    </div>

                </div>

                <div class="form-group col">

                    <div class="e-float-input">

                        <input id="FirstName" type="text" [(ngModel)]="value" formControlName="FirstName"/>

                        <span class="e-float-line"></span>

                        <label class="e-float-text">First Name</label>

                    </div>

                    <div *ngIf="FirstName.errors ">

                        <div *ngIf="FirstName.errors.required && FirstName.touched" class="e-error">

                            Please enter first name.

                        </div>

                    </div>

                </div>

               

          

            <div class="row">

                <div style="width: 320px;margin:0px auto;height: 100px;padding-top: 25px;">

                    <div style="display: inline-block;">

                        <button id="validateSubmit" class="samplebtn e-control e-btn e-primary" type="submit" style="height:40px;width: 150px;" data-ripple="true">Add Customer</button>

                    </div>

                    <div style="float: right;">

                        <button id="resetbtn" class="samplebtn e-control e-btn" type="reset" style="height:40px;width: 150px;" data-ripple="true">Clear</button>

                    </div>

                </div>

            </div>

        </form>

 


Regards 

Charles



PS Pavithra Subramaniyam Syncfusion Team September 16, 2022 09:37 AM UTC

Hi Charles,


Since the reported query is related to EJ2 DropDownList component, we have created a new forum “Branched from forum-173400” under your account. For more updates regarding the above query please follow up on the new one.


Also, we request you to create a new forum for new queries in the future. This will help for better follow up.


Regards,

Pavithra S



PS Pavithra Subramaniyam Syncfusion Team September 20, 2022 02:18 PM UTC

Hi Charles,


If you want to change the text box value while changing a dropdown list value, then you can achieve your requirement by adding the “change” event to the DropDownList and inside this event, you can set the textbox value. Please refer to the below code example for more information.


write: (args) => {

  this.prefixObj = new DropDownList({

    fields: { value: 'PrefixId', text: 'PrefixName' },

    .  .  .

    change: (args) => {

      // here this.grid is Grid instance  and “CustomerID” is the corresponding field of the required textbox

      this.grid.editModule.formObj.element.querySelector("#" + this.grid.element.id + "CustomerID").ej2_instances[0].value = args.itemData.PrefixId;

    }

  });

  this.prefixObj.appendTo(this.prefixElem);

 

}

 


Please get back to us if you need further assistance on this.


Regards,

Pavithra S


Loader.
Up arrow icon