Angular 7 SlickGrid Detail-View: невозможно передать EventEmitter из компонента Detail-View (дочерний) в компонент SlickGrid (родительский) - PullRequest
0 голосов
/ 09 января 2020

Я использую Angular SlickGrid в качестве родительского компонента и плагин Detail-View в качестве дочернего компонента. В компоненте Detail-View я использую несколько кнопок для конкретных c задач. Одним из них является кнопка Удалить. Проблема в том, что при нажатии кнопки запускается служба компонентов, которая удаляет выбранную строку из сетки по ее идентификатору. Бэкэнд работает отлично. НО! На внешней стороне этот ряд все еще виден, если я не перезагружу страницу вручную. И мне нужно, чтобы строка из родительского компонента была удалена при клике. Я пытался использовать EventEmitters, но SlickGrid, как правило, не распознает эту функцию. Если бы все было в одном компоненте, я мог бы упростить использование: this.angularGrid.gridService.deleteItemById(del_id);, но так как данные подробного просмотра передаются rowDetailView в this.gridOptions, нет тегов шаблона компонента, таких как <app-row-detail-view></app-row-detail-view>

Мой Детальный просмотр (дочерний) :

  @Input() del_id: string;
  @Output() onDelete = new EventEmitter<string>();

  model: {
    id: string;
    domains: string;
    example_site: string;
    status: string;
    created: string;
    image: string;
  };

  deleteRecipe() {
    if (confirm('Are You sure?')) {
      console.log("EVENT 1");
      this.del_id = this.model.id;
      this.onDelete.emit(this.del_id);
      console.log(this.del_id);
      return this.recipeService.removeRecipe(this.del_id)
      .subscribe(u => {
        return u;
      });
    }
  }

Мой Детальный просмотр HTML (дочерний) :

<button (click)="deleteRecipe()">DELETE</button>

Мой компонент PARENT HTML:

<angular-slickgrid
      gridId="grid11"
      [columnDefinitions]="columnDefinitions"
      [gridOptions]="gridOptions"
      [gridWidth]=1500
      [dataset]="dataset"
      (onAngularGridCreated)="angularGridReady($event)"
      (onDelete)="onDeleted($event)"
      >
</angular-slickgrid>

и я не могу использовать здесь что-то вроде [del_id]="del_id" Потому что я получаю большую ошибку в консоли ..

Мой родительский компонент .ts :

  onDeleted(del_id: string) {
    console.log("EVENT 2");
    console.log(del_id);
    this.angularGrid.gridService.deleteItemById(del_id);
  }

  this.gridOptions = {
      enableAsyncPostRender: true,
      enableFiltering: true,
      enableAutoResize: true,
      enableCellNavigation: true,
      enableGrouping: false,
      enableRowDetailView: true,
      enableColumnReorder: false,
      rowSelectionOptions: {
        selectActiveRow: true
      },
      rowDetailView: {
        process: (item: any) => this.simulateServerAsyncCall(item),
        viewComponent: RecipeDetailsComponent,
        loadOnce: true,
        singleRowExpand: true,
        useRowClick: true,
        panelRows: this.detailViewRowCount
      }
    };

  simulateServerAsyncCall(item: any) {
    return new Promise((resolve) => {
      const itemDetail = item;
      resolve(itemDetail);
    });
  }

Я перепробовал множество статей о EventEmitters, например: https://github.com/6pac/SlickGrid/blob/master/plugins/slick.rowdetailview.js#L10, https://www.infragistics.com/community/blogs/b/infragistics/posts/understanding-output-and-eventemitter-in-angular , https://github.com/ghiscoding/Angular-Slickgrid/blob/master/src/app/modules/angular-slickgrid/models/rowDetailView.interface.ts.

Любая помощь будет принята с благодарностью! Заранее благодарю уважаемые коллеги!

1 Ответ

1 голос
/ 20 января 2020

Обратите внимание, что я являюсь автором Angular -Slickgrid .

Я согласен, что это было сложно сделать в предыдущей версии, поэтому для решения этой проблемы я добавил новые ссылки на SlickGrid, ссылки на DataView, а также экземпляр родительского компонента на расширение Row Detail, так что теперь вы можете получить доступ ко всем этим новым ссылкам в свой дочерний компонент. Чтобы воспользоваться этими новыми изменениями, пожалуйста, обновитесь до последней Angular -Slickgrid версии 2.16.x .

Теперь с этими ссылками вы можете воспользоваться ими и изменить свой дочерний компонент сведений о строке на следующий

Вы можете увидеть живую демонстрацию своего вопроса (как удалить строку из дочернего элемента). Компонент) в обновленном примере Подробная информация о строке , а также я обновил Подробную информацию о строке Wiki

Дочерний компонент - Просмотр подробных сведений о строке

<div class="container-fluid">
  <h3>{{model?.title}}</h3>

    <button class="btn btn-primary btn-danger btn-sm" (click)="deleteRow(model)" data-test="delete-btn">
      Delete Row
    </button>
    <button class="btn btn-default btn-sm" (click)="callParentMethod(model)" data-test="parent-btn">
      Call Parent Method
    </button>
</div>

Дочерний компонент - Компонент детализации строки

import { Component } from '@angular/core';
import { GridRowDetailComponent } from './grid-rowdetail.component';

@Component({
  templateUrl: './rowdetail-view.component.html'
})
export class RowDetailViewComponent {
  model: {
    duration: Date;
    percentComplete: number;
    reporter: string;
    start: Date;
    finish: Date;
    effortDriven: boolean;
    assignee: string;
    title: string;
  };

  // you also have access to the following objects (it must match the exact property names shown below)
  addon: any; // row detail addon instance
  grid: any;
  dataView: any;

  // you can also optionally use the Parent Component reference
  // NOTE that you MUST provide it through the "parent" property in your "rowDetail" grid options
  parent: GridRowDetailComponent;

  constructor() { }

  alertAssignee(name: string) {
    if (typeof name === 'string') {
      alert(`Assignee on this task is: ${name.toUpperCase()}`);
    } else {
      alert('No one is assigned to this task.');
    }
  }

  deleteRow(model) {
    if (confirm(`Are you sure that you want to delete ${model.title}?`)) {
      // you first need to collapse all rows (via the 3rd party addon instance)
      this.addon.collapseAll();

      // then you can delete the item from the dataView
      this.dataView.deleteItem(model.id);

      this.parent.showFlashMessage(`Deleted row with ${model.title}`, 'danger');
    }
  }

  callParentMethod(model) {
    this.parent.showFlashMessage(`We just called Parent Method from the Row Detail Child Component on ${model.title}`);
  }
}
Родительский компонент - Сетка
<div class="container-fluid">
  <h2>{{title}}</h2>
  <div class="subtitle" [innerHTML]="subTitle"></div>

  <div class="alert alert-{{flashAlertType}} col-sm-6" *ngIf="message" data-test="flash-msg">{{message}}</div>

  <hr />

  <angular-slickgrid gridId="grid21" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
    [dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)">
  </angular-slickgrid>
</div>
Представление родительского компонента
import { Component, OnInit } from '@angular/core';
import {
  AngularGridInstance,
  Column,
  ExtensionName,
  FieldType,
  Filters,
  Formatters,
  GridOption
} from './../modules/angular-slickgrid';
import { RowDetailViewComponent } from './rowdetail-view.component';
import { RowDetailPreloadComponent } from './rowdetail-preload.component';


@Component({
  templateUrl: './grid-rowdetail.component.html'
})
export class GridRowDetailComponent implements OnInit {
  angularGrid: AngularGridInstance;
  columnDefinitions: Column[];
  gridOptions: GridOption;
  dataset: any[];
  detailViewRowCount = 9;
  message: string;
  flashAlertType = 'info';

  constructor() { }

  angularGridReady(angularGrid: AngularGridInstance) {
    this.angularGrid = angularGrid;
  }

  get rowDetailInstance(): any {
    return this.angularGrid && this.angularGrid.extensionService.getSlickgridAddonInstance(ExtensionName.rowDetailView) || {};
  }

  ngOnInit(): void {
    this.defineGrid();
  }

  /* Define grid Options and Columns */
  defineGrid() {
    this.columnDefinitions = [ /** ... */ ];

    this.gridOptions = {
      autoResize: {
        containerId: 'demo-container',
        sidePadding: 15
      },
      enableFiltering: true,
      enableRowDetailView: true,
      rowSelectionOptions: {
        selectActiveRow: true
      },
      rowDetailView: {
        // We can load the "process" asynchronously in 2 different ways (httpClient OR even Promise)
        process: (item) => this.simulateServerAsyncCall(item),
        // process: (item) => this.http.get(`api/item/${item.id}`),

        // load only once and reuse the same item detail without calling process method
        loadOnce: true,

        // limit expanded row to only 1 at a time
        singleRowExpand: false,

        // false by default, clicking anywhere on the row will open the detail view
        // when set to false, only the "+" icon would open the row detail
        // if you use editor or cell navigation you would want this flag set to false (default)
        useRowClick: true,

        // how many grid rows do we want to use for the row detail panel (this is only set once and will be used for all row detail)
        // also note that the detail view adds an extra 1 row for padding purposes
        // so if you choose 4 panelRows, the display will in fact use 5 rows
        panelRows: this.detailViewRowCount,

        // you can override the logic for showing (or not) the expand icon
        // for example, display the expand icon only on every 2nd row
        // expandableOverride: (row: number, dataContext: any, grid: any) => (dataContext.id % 2 === 1),

        // Preload View Component
        preloadComponent: RowDetailPreloadComponent,

        // View Component to load when row detail data is ready
        viewComponent: RowDetailViewComponent,

        // Optionally pass your Parent Component reference to your Child Component (row detail component)
        parent: this
      }
    };

    this.getData();
  }


  closeAllRowDetail() {
    if (this.angularGrid && this.angularGrid.extensionService) {
      this.rowDetailInstance.collapseAll();
    }
  }

  showFlashMessage(message: string, alertType = 'info') {
    this.message = message;
    this.flashAlertType = alertType;
  }

}
...