How can I nest a kendo-grid within another kendo-grid and make them both editable with on-cell click functionality?

I am facing an issue with my 2 components - trial1 (parent kendo-grid) and trial2 (child kendo-grid). Inside the template of trial1, I referenced the sub-grid component trial2. However, I am encountering an error where trial2 is not recognized inside trial1.

<ng-template kendoGridToolbarTemplate>
  <button kendoGridAddCommand type="button" class="btn btn--secondary btn--small addTableRow"><span class="icon-add"></span></button>
  <button *ngIf="formGroup" (click)="cancelHandler()" class="k-button k-primary">Cancel</button>
</ng-template>

<kendo-grid-column *ngFor="let details of dTable.columns;let i = index;" [field]="details.field" [title]="details.title" width="details.width" [editable]="true">
</kendo-grid-column>

<ng-template kendoGridDetailTemplate let-dataItem>

    <trial2></trial2>

  </ng-template>

<kendo-grid-command-column title="command" width="100">
    <ng-template kendoGridCellTemplate let-isNew="isNew">
        <button kendoGridRemoveCommand class="label label--circle label--small btn btn--secondary show icon-presence-end">X</button>
    </ng-template>
</kendo-grid-command-column>

</kendo-grid>

I would appreciate solutions in Angular (not JQuery). Thank you.

Answer №1

To see a demonstration of the master-detail grid, please visit the master-detail grid demo. To enable in-cell editing, you must add the following events to both the master and detail grid components:

  • cellClick -> Display input when a cell is clicked
  • cellClose -> Save data when leaving a cell
//Master component
@Component({
    providers: [CategoriesService],
    selector: 'my-app',
    template: `
      <kendo-grid
          [data]="view | async"
          [loading]="view.loading"
          [pageSize]="pageSize"
          [skip]="skip"
          [sortable]="true"
          [sort]="sort"
          [pageable]="true"
          [height]="550"
          [navigable]="true"
          (dataStateChange)="dataStateChange($event)"
          (cellClick)="cellClickHandler($event)"
          (cellClose)="cellCloseHandler($event)"
        >
        <kendo-grid-column field="CategoryID" width="100"></kendo-grid-column>
        <kendo-grid-column field="CategoryName" width="200" title="Category Name"></kendo-grid-column>
        <kendo-grid-column field="Description" [sortable]="false">
        </kendo-grid-column>
        <div *kendoGridDetailTemplate="let dataItem">
            <category-details [category]="dataItem"></category-details>
        </div>
      </kendo-grid>
  `
})
export class AppComponent implements OnInit, AfterViewInit {
    public view: Observable<GridDataResult>;
    public sort: Array<SortDescriptor> = [];
    public pageSize = 10;
    public skip = 0;

    @ViewChild(GridComponent) grid: GridComponent;

    constructor(private formBuilder: FormBuilder, private service: CategoriesService) { }

    public ngOnInit(): void {
        // Bind directly to the service as it is a Subject
        this.view = this.service;

        // Fetch the data with the initial state
        this.loadData();
    }

    public dataStateChange({ skip, take, sort }: DataStateChangeEvent): void {
        // Save the current state of the Grid component
        this.skip = skip;
        this.pageSize = take;
        this.sort = sort;

        // Reload the data with the new state
        this.loadData();
    }

    public ngAfterViewInit(): void {
        // Expand the first row initially
        this.grid.expandRow(0);
    }

    private loadData(): void {
        this.service.query({ skip: this.skip, take: this.pageSize, sort: this.sort });
    }

    public cellClickHandler({ sender, rowIndex, columnIndex, dataItem, isEdited }) {
        if (!isEdited) {
          console.log(sender);
            sender.editCell(rowIndex, columnIndex, this.createFormGroup(dataItem));
        }
    }

    public cellCloseHandler(args: any) {
        const { formGroup, dataItem } = args;

        if (!formGroup.valid) {
             // prevent closing the edited cell if there are invalid values.
            args.preventDefault();
        } else if (formGroup.dirty) {
            console.log("save data")
        }
    }

    public createFormGroup(dataItem: any): FormGroup {
        return this.formBuilder.group({
            'CategoryID': dataItem.CategoryID,
            'CategoryName': [dataItem.CategoryName, Validators.required],
            'Description': [dataItem.Description, Validators.required],
        });
    }
}
//Detail component
@Component({
    selector: 'category-details',
    providers: [ProductsService],
    template: `
      <kendo-grid
          [data]="view | async"
          [loading]="view.loading"
          [pageSize]="5"
          [skip]="skip"
          [pageable]="true"
          [scrollable]="'none'"
          (pageChange)="pageChange($event)"

          [navigable]="true"
          kendoGridFocusable
          (cellClick)="cellClickDetailsHandler($event)"
          (cellClose)="cellCloseDetailsHandler($event)"
        >
      <kendo-grid-column field="ProductID" title="Product ID" width="120">
      </kendo-grid-column>
      <kendo-grid-column field="ProductName" title="Product Name">
      </kendo-grid-column>
      <kendo-grid-column field="UnitPrice" title="Unit Price" format="{0:c}">
      </kendo-grid-column>
      </kendo-grid>
  `
})
export class CategoryDetailComponent implements OnInit {

    /**
     * The category for which details are displayed
     */
    @Input() public category: Object;

    public view: Observable<GridDataResult>;
    public skip = 0;

    constructor(private formBuilder: FormBuilder,private service: ProductsService) { }

    public ngOnInit(): void {
        this.view = this.service;

        /*load products for the given category*/
        this.service.queryForCategory(this.category, { skip: this.skip, take: 5 });
    }

    public pageChange({ skip, take }: PageChangeEvent): void {
        this.skip = skip;
        this.service.queryForCategory(this.category, { skip, take });
    }

     public cellClickDetailsHandler({ sender, rowIndex, columnIndex, dataItem, isEdited }) {
        if (!isEdited) {
          console.log(sender);
            sender.editCell(rowIndex, columnIndex, this.createFormGroupDetail(dataItem));
        }
    }

    public cellCloseDetailsHandler(args: any) {
        const { formGroup, dataItem } = args;

        if (!formGroup.valid) {
             // prevent closing the edited cell if there are invalid values.
            args.preventDefault();
        } else if (formGroup.dirty) {
            console.log("save data")
        }
    }

    public createFormGroupDetail(dataItem: any): FormGroup {
        return this.formBuilder.group({
            'ProductID': dataItem.ProductID,
            'ProductName': [dataItem.ProductName, Validators.required],
            'UnitPrice': dataItem.UnitPrice,
            'UnitsInStock': [dataItem.UnitsInStock, Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])],
            'Discontinued': dataItem.Discontinued
        });
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be causing Bootstrap to fail in my fresh Angular project?

Upon creating a fresh angular project, I proceeded to install bootstrap using npm. Once it was successfully installed in my node_modules folder, I added it to my angular.json file. "styles": [ "/node_modules/bootstrap/dist/css/ ...

The onShown event in ngx-bootstrap's datePicker is fired just before the calendar actually becomes visible

Recently, I've been exploring the capabilities of ngx-bootstrap's rangeDatePicker. My current challenge involves attempting to automatically navigate to the previous month as soon as the user opens the rangeDatePicker. To accomplish this, I have ...

Issue with running Angular Application through docker-compose.yml file is stopping the execution

Below is the docker file I have created for my angular application: Dockerfile: # base image FROM node:10.16.0-alpine AS build-step # set working directory WORKDIR /app COPY package.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:1.16.1-alp ...

The Sourcemap is not correctly aligning with the expected line number

Currently working with the angular2-webpack-starter technology and utilizing VSCode along with Chrome debugger. After numerous attempts, I was able to successfully set a breakpoint, but it appears that the line mapping is incorrect. The issue persists in ...

Having trouble adding npm package to Angular project due to npm error ERESOLVE?

I encountered this error while attempting to install any package with npm. I have attempted to clear the cache and reinstall node itself, but none of these methods have worked. -- Error message D:\Electrolux KB\Electrolux-KnowledgeBase.eg_v2> ...

Code snippet demonstrating how to use multiple filters in Angular 2

Exploring the world of AngularJS, I am striving to replicate the functionality provided in this JSFiddle using Angular 2. In my previous attempt with Angular 1, this was the HTML code I utilized: Essentially, I have an array structured like: [ {name: ...

The issue with Angular 2's Parameterised router link component not fully refreshing

I'm trying to figure out how to show a set of images when I click on a specific menu item. The menu structure looks like this: <ul id="demo23" class="collapse"> <li> <a [routerLink]="['image-gallery','Picasso ...

JHipster form validation is failing to function properly

I have a specific class structure that is defined as follows in JDL entity Address { address String required, city String required, postalCode String required, country String required, } entity MainEntity { <some fields> } relationship O ...

Using TypeScript with Angular-UI Modals

Currently, my goal is to create a modal using angular-ui-bootstrap combined with typescript. To begin, I referenced an example from this link (which originally utilizes jQuery) and proceeded to convert the jQuery code into typescript classes. After succes ...

Issue: Module '@nrwl/workspace/src/utilities/perf-logging' not found

I attempted to run an Angular project using nxMonorepo and made sure to install all the necessary node modules. However, when I tried running the command "nx migrate --run-migrations" in my directory PS C:\Users\Dell\Desktop\MEANAPP&bso ...

How to ensure that Excel recognizes dates as actual dates in a column automatically when using xlsx in Angular

I have a specialized Angular service that is capable of generating excel files: import { Injectable } from '@angular/core'; import * as FileSaver from 'file-saver'; import * as XLSX from 'xlsx'; const EXCEL_TYPE = 'appli ...

UI not reflecting updated form validation after changes made

Currently, I have a situation where I am passing a form from the Parent component to the Child component. All the validations are being handled in the Parent component and the Child component is simply rendering it. However, there is a specific field calle ...

Implementing a global provider in Ionic 3

I have integrated a provider in my app that needs to stay active at all times while the application is running to monitor the network connection status. Following this guide, I included the class in my app.module.ts file to ensure it functions as a global ...

The React component was not able to receive any children as input

My Typescript-written React component is called GradientText.tsx: import React, { ReactNode } from "react" import { cn } from "@/lib/utils" const typeMap = { h1: "h1", h2: "h2", p: "p", } inte ...

The string variable in the parent app is resetting to empty after being populated by the service call

I am facing an issue with my app components where AppComponent acts as the parent and ConfigComponent as the child. In the constructor of AppComponent, a service call is made to set a variable but I encounter unexpected behavior when trying to access this ...

There is an error appearing in my .ts code: [ts] The property 'name' is not found in type 'any[]'

While my coding is working fine and data is showing on the page, there seems to be an error occurring in the VSE editor. It is showing something like this: [ts] Property 'name' does not exist on type 'any[]'. This is a snippet of my ...

Utilizing TypeScript in an AngularJS (1.x) project alongside Webpack: A Step-By-Step Guide

Currently, I am working through the official guide on transitioning from AngularJS (1.x) to Angular (2+). I have successfully divided my application into Components and integrated ES6 with Webpack as the module loader. However, I now find myself unsure of ...

Modifying the value of a React input component is restricted when the "value" field is utilized

I'm currently utilizing material-UI in my React application. I am facing a challenge where I need to remove the value in an input field by clicking on another component. The issue arises when using the OutlinedInput component with a specified value. ...

Search functionality in Angular using column-based filtering algorithm

Take a look at my table view below. Each column has its own search function. My current issue is that when I type in one column, the same text appears in other columns as well. To solve this problem, I have implemented the following code: <tr& ...

Leveraging react-share in combination with react-image-lightbox

I have recently inherited a React project and am struggling to integrate react-share with react-image-lightbox. My experience with both React and Typescript is limited, so any assistance would be greatly appreciated. Below are the relevant code snippets: ...