Как изменить значение параметров gridster2 при нажатии кнопки в angular

#javascript #angular #typescript #angular-gridster2

#javascript #angular #typescript #angular-gridster2

Вопрос:

вот код и вывод: https://stackblitz.com/edit/d3-angular-gridster2-working-axhc7u?file=src/app/grid/grid.component.html

СЕТКА-HTML

 <gridster [options]="options">
  <gridster-item [item]="item" *ngFor="let item of dashboard">
   
  </gridster-item>
</gridster>
  

GRID-TS

 ngOnInit() {
  @Input() editing: any;
    this.options = {
      gridType: GridType.Fit,
      displayGrid: DisplayGrid.Always,
      enableEmptyCellClick: false,
      enableEmptyCellContextMenu: false,
      enableEmptyCellDrop: false,
      enableEmptyCellDrag: false,
      enableOccupiedCellDrop: false,
      emptyCellClickCallback: this.emptyCellClick.bind(this),
      emptyCellContextMenuCallback: this.emptyCellClick.bind(this),
      emptyCellDropCallback: this.emptyCellClick.bind(this),
      emptyCellDragCallback: this.emptyCellClick.bind(this),
      emptyCellDragMaxCols: 50,
      emptyCellDragMaxRows: 50
    };

    this.dashboard = [
      { cols: 2, rows: 1, y: 0, x: 0 },
      { cols: 2, rows: 2, y: 0, x: 2 },
      { cols: 1, rows: 1, y: 0, x: 4 },
      { cols: 3, rows: 2, y: 1, x: 4 },
      { cols: 1, rows: 1, y: 4, x: 5 },
      { cols: 1, rows: 1, y: 2, x: 1 },
      { cols: 2, rows: 2, y: 5, x: 5 },
      { cols: 2, rows: 2, y: 3, x: 2 },
      { cols: 2, rows: 1, y: 2, x: 2 },
      { cols: 1, rows: 1, y: 3, x: 4 },
      { cols: 1, rows: 1, y: 0, x: 6 }
    ];
  }
  

Что я пытаюсь здесь сделать, так это включить enableEmptyCellDrag .
например, я нажал кнопку edit, затем значение edit равно true , а затем значение enableEmptyCellDrag равно true .

Я уже пробовал это:

 ngOnChanges() {
 ///this.options['enableEmptyCellDrag'] = true // the enableEmptyCellDrag is undefined
 ///if (this.editing) {
 /// this.options['enableEmptyCellDrag'] = true // the value of enableEmptyCellDrag is change to true, but when I try to drag from the empty cell it doesn't work
 ///}

}
  

Ответ №1:

Если я правильно понимаю, вы хотите установить this.options['enableEmptyCellDrag'] значение @Input() editing .

И вы хотите, чтобы gridster2 (должен признать, я не знаю, что это такое) распознал изменение.

Итак, у вас есть 2 проблемы:

  1. Когда вы войдете ngOnChanges , доступ к вашему @Input() напрямую даст вам «старое» значение.

  2. Обычно, чтобы Angular обнаруживал изменения в объектах, вам необходимо изменить ссылку на объект.

Итак, вот как вы ngOnChanges должны выглядеть.

   ngOnChanges(changes: SimpleChanges) {
    if (changes.editing amp;amp; changes.editing.currentValue) {
      // Solve problem 1)
      const newValueOfEditingInput = changes.editing.currentValue;

      // Solve Problem 2) - Create a new reference for this.options, so that angular (grister2) can detect the change
      this.options = {
        ...this.options,
        enableEmptyCellDrag: newValueOfEditingInput
      };
    }
  }
  

Конечно, я не тестировал это, но я надеюсь, что это может вам помочь

Комментарии:

1. Вопрос, что делать, если он отменяется. он не должен перетаскиваться.

2. Извините, как я уже сказал, я хорошо разбираюсь в Angular, но я не знаю этот компонент gridster или чего он должен достичь, поэтому мне сложно помочь вам в этом

3. мм .. как оно вернется к false? причина, когда я нажимаю редактировать значение enableEmptyCellDrag . но когда оно равно false, оно все равно true.

4. Я согласен, но не понимаю, почему это так беспорядочно … ваше назначение параметров обратно самому себе позволяет gridster обнаруживать и инициировать любые изменения, объявленные в параметрах… но, как правило, мне просто нужно изменить параметр, который будет обнаружен, по крайней мере, в большинстве фреймворков… это кажется странным.

5. Понимание этого ключа к избежанию ошибок в Angular (и в любом фреймворке javascript в целом). Обнаружение изменений работает, когда вы меняете ссылку на ввод. И если ваш @Input является объектом или массивом, изменение внутренних свойств не изменит ссылку (что не приведет к обнаружению изменений). Я согласен и понимаю, что это очень запутанно в мире javascript, это настоящая проблема для освоения.

Ответ №2:

Я нашел более элегантное решение, ИМХО.

Объект GridsterConfig имеет подобъект api.optionsChanged, который является функцией. Если вы запустите его, это также сообщит Gridster, что параметры изменяются без необходимости, по сути, повторного создания объекта (который, вероятно, просто запускает эту функцию в любом случае). Кажется более безопасным и элегантным.

Таким образом, ваше изменение on теперь может выглядеть так:

   ngOnChanges(changes: SimpleChanges) {
    if (changes.editing amp;amp; changes.editing.currentValue) {
      this.options.enableEmptyCellDrag = changes.editing.currentValue;
      this.options.api.optionsChanged();
    }
  }
  

Я также предлагаю создать класс, подобный следующему, который не позволит вам проверять, существуют ли эти параметры или нет (оператор if просто проверяет, определены ли дополнительные параметры интерфейса GridsterConfig… так что, если вы определите их заранее, в этом нет необходимости … не уверен, почему Gridster сделал существование необязательным… IMHO параметры всегда должны существовать, но могут быть установлены в null или по умолчанию).

 export class DashboardOptions implements GridsterConfig{
  gridType = GridType.Fit;
  compactType = CompactType.None;
  margin = 10;
  outerMargin = false;
  outerMarginTop = null;
  outerMarginRight = null;
  outerMarginBottom = null;
  outerMarginLeft = null;
  useTransformPositioning = true;
  mobileBreakpoint = 720;
  minCols = 1;
  maxCols = 100;
  minRows = 1;
  maxRows = 100;
  maxItemCols = 100;
  minItemCols = 1;
  maxItemRows = 100;
  minItemRows = 1;
  maxItemArea = 2500;
  minItemArea = 1;
  defaultItemCols = 1;
  defaultItemRows = 1;
  fixedColWidth = 105;
  fixedRowHeight = 105;
  keepFixedHeightInMobile = false;
  keepFixedWidthInMobile = false;
  scrollSensitivity = 10;
  scrollSpeed = 20;
  enableEmptyCellClick = false;
  enableEmptyCellContextMenu = false;
  enableEmptyCellDrop = false;
  enableEmptyCellDrag = false;
  enableOccupiedCellDrop = false;
  emptyCellDragMaxCols = 50;
  emptyCellDragMaxRows = 50;
  ignoreMarginInRow = false;
  public draggable = {
    enabled: false,
    delayStart: 200,
    start: () => {},
    stop: () => {}
  };
  public resizable = {
    enabled: true,
    delayStart: 200,
    start: () => {},
    stop: () => {}
  };
  swap = false;
  pushItems = true;
  disablePushOnDrag = false;
  disablePushOnResize = false;
  pushDirections = {north: true, east: true, south: true, west: true};
  pushResizeItems = false;
  displayGrid = DisplayGrid.Always;
  disableWindowResize = false;
  disableWarnings = false;
  scrollToNewItems = false;
  api = {
    resize: () => {},
    optionsChanged: () => {},
  };
  itemChangeCallback = (item: GridsterItem, itemComponent: GridsterItemComponentInterface) => {};
}
  

Тогда ваше изменение при изменении теперь может выглядеть так:

   ngOnChanges(changes: SimpleChanges) {
      this.options.enableEmptyCellDrag = changes.editing.currentValue;
      this.options.api.optionsChanged();
  }