Настройка панели управления, пользовательские кнопки, инструменты работы с объектами на списках, блокирование отдельных ячеек, иерархический список, вычислимые свойства

Списки для разных систем требуют разного, часто индивидуального, подхода. Для этих целей в компоненте Flexberry Objectlistview реализован ряд механизов, позволяющих настравивать как панель управления, так и отдельные строки, ячейки или внешний вид.

Настройка панели управления для списков

Панель управления (тулбар) Flexberry Objectlistview основана на технологическом контроле olv-toolbar.

Настройка панели управления происходит через компонент Flexberry Objectlistview.

Кнопка создания новой записи


{{flexberry-objectlistview
  createNewButton = true
}}

createNewButton - флаг, определяющий, отображать ли кнопку создания на панели управления.

Кнопка обновления


{{flexberry-objectlistview
  refreshButton = true
}}

refreshButton - флаг, определяющий, отображать ли кнопку обновления на панели управления.

Кнопка удаления выделенных записей

{{flexberry-objectlistview
  componentName = "..."
  deleteButton = true
  showCheckBoxInRow = true
  ...
}}

Для того чтобы начала функционировать кнопка удаления выделенных записей, требуется определить следующие свойства:

  • componentName - имя контрола (используется для идентификации составных частей контрола, которые взаимодействуют через внедрённый сервис). Например, в качестве значения для списка записей типа “employee” можно указать “employeesFlexberryObjectListView”.
  • deleteButton - флаг, определяющий, отображать ли кнопку удаления на панели управления.
  • showCheckBoxInRow - флаг, определяющий, отображать ли чекбокс в строке

При удалении информация сразу отправляется на сервер для сохранения изменений.

Пользовательские кнопки для списков

Встраивание пользовательских кнопок в тулбар списка

Для встраиваемой кнопки в контроллере формы нужно определить ряд свойств:

{
    buttonName: '...', // Отображаемое имя кнопки.
    buttonAction: '...', // Действие, вызываемое контроллером при нажатии этой кнопки (должно быть указано в шаблоне).
    buttonClasses: '...', // Css-класс кнопки.
    buttonTitle: '...' // Подпись.
}

Если необходимо добавить несколько кнопок, то их свойства задаются в массиве:

[{ buttonName: ..., buttonAction: ..., buttonClasses: ... }, {...}, ...]

Для того чтобы добавить в тулбар списка пользовательскую кнопку, в контроллере нужно определить метод customButtonsMethod. Например:

import Ember from 'ember';
import ListFormController from 'ember-flexberry/controllers/list-form';

export default ListFormController.extend({
...
customButtonsMethod: Ember.computed('i18n.locale', function() {
    let i18n = this.get('i18n');
    return [{
        buttonName: i18n.t('forms.components-examples.flexberry-objectlistview.toolbar-custom-buttons-example.custom-button-name'),
        buttonAction: 'userButtonActionTest',
        buttonClasses: 'test-click-button'
        }];
    })
});

Далее, в контроллере, нужно указать событие buttonAction

...
clickCounter: 1,
messageForUser: undefined,

actions: {
    userButtonActionTest: function() {
    let i18n = this.get('i18n');
    let clickCounter = this.get('clickCounter');
    this.set('clickCounter', clickCounter + 1);
    this.set('messageForUser',
        i18n.t('forms.components-examples.flexberry-objectlistview.toolbar-custom-buttons-example.custom-message').string +
        ' ' + clickCounter);
    }
}
});

Определенные методы и свойства должны быть указаны в шаблоне списка:

{{flexberry-objectlistview
...
customButtons=customButtonsMethod
userButtonActionTest='userButtonActionTest'
}}

Встраивание пользовательских кнопок в строки списка

Пользовательские кнопки для строк списка создаются по аналогичному принципу. Событие, как и для кнопки в тулбаре, может быть задано строкой. Например, так:

...
actions: {
    userButtonInRowActionTest(model) {
      this.set('modelFromClickedRow', model);
    },
});

Кнопки пользовательских настроек

При значении атрибута colsConfigButton=true на панели управления отображаются кнопки управления пользовательскими наcтройками.

{{flexberry-objectlistview
  componentName = "..."
  colsConfigButton=true
  ...
}}

Подробно о функционале пользовательских настроек можно почитать в статье Сервис настроек пользователя.

Добавление пользовательских кнопок на панель управления

На панель управления можно добавлять кнопки, реализующие пользовательскую логику. Чтобы добавить пользовательскую кнопку, требуется выполнить следующее:

1.В соответствующем прикладном контроллере определить вычислимое свойство с произвольным именем, например, сustomButtons, которое возвращает массив структур вида:

{
 buttonName: '...',
 buttonAction: '...',
 buttonClasses: '...',
 disabled: true,
}
  • buttonName - имя кнопки на интерфейсе пользователя. Если передано пустое значение, то имя кнопки будет ‘UserButton’.
  • buttonAction - имя действия (action), которое будет вызываться данной кнопкой (при вызове действия используется sendAction, поэтому обработчик можно определять как в контроллере, так и в соответствующем роуте). Если передано пустое значение, то в консоли браузера появится сообщение об ошибке. Желательно именовать действия с префиксом “userButtonAction”, чтобы случайно не перетереть свойство контрола при регистрации этого действия.
  • buttonClasses - классы, которые требуется добавить в создаваемую пользовательскую кнопку.
  • disabled - логическое свойство, отвечающее за состояние кнопки, если true кнопка неактивна, иначе, активна.

2.В соответствующем прикладном контроллере (или роуте) определить обработчик события, имя которого было указано в buttonAction.

3.В шаблоне соответствующей формы у компонента flexberry-objectlistview определить свойства:


{{flexberry-objectlistview
  // ...
  customButtons=customButtons  
  userButtonAction1='userButtonAction1'
  userButtonAction2='userButtonAction2'
  // ...
  userButtonActionN='userButtonActionN'
}}
  • customButtons - определение свойства, откуда можно взять массив.
  • userButtonAction1, userButtonAction2, … userButtonActionN - регистрация действий, которые определялись в свойстве buttonAction (без такой “регистрации” действие может не вызываться и Ember не выдаст сообщения об ошибке).

Пример использования пользовательской кнопки на списке

Например, требуется добавить пользовательскую кнопку, которая при клике будет выводить сообщение пользователю.

1.В шаблоне страницы задать заголовок в виде переменной “header”.

<h3 class="ui header">Страница с пользовательскими кнопками</h3>
<div class="row">
  {{flexberry-objectlistview
    // ...
    customButtons=customButtons
    userButtonAction1='userButtonAction1'
    userButtonAction2='userButtonAction2'
    // ...
    userButtonActionN='userButtonActionN'
  }}
</div>
<div class="row">{{messageForUser}}</div>

2.В контроллере определить необходимые переменные, задать вычислимое локализируемое свойство “customButtons”, которое вернёт массив описаний пользовательских кнопок (в данном случае - одной кнопки), и действие “userButtonActionTest”, которое будет обрабатывать нажатие на кнопку.

import Ember from 'ember';
import ListFormController from 'ember-flexberry/controllers/list-form';

export default ListFormController.extend({
  /**
    Property to count clicks on user button.

    @property clickCounter
    @type Number
    @default 1
   */
  clickCounter: 1,

  /**
    Property to show user message after click on user button.

    @property messageForUser
    @type String
   */
  messageForUser: undefined,

  /**
    Property to form array of special structures of custom user buttons.

    @property customButtons
    @type Array
   */
  customButtons: Ember.computed('i18n.locale', function() {
    let i18n = this.get('i18n');
    return [{
      buttonName: i18n.t('forms.components-examples.flexberry-objectlistview.toolbar-custom-buttons-example.custom-button-name'),
      buttonAction: 'userButtonActionTest',
      buttonClasses: 'my-test-user-button test-click-button'
    }];
  }),

  actions: {
    /**
      Handler for click on custom user button.

      @method userButtonActionTest
     */
    userButtonActionTest: function() {
      let i18n = this.get('i18n');
      let clickCounter = this.get('clickCounter');
      this.set('clickCounter', clickCounter + 1);
      this.set('messageForUser',
        i18n.t('forms.components-examples.flexberry-objectlistview.toolbar-custom-buttons-example.custom-message').string +
        ' ' + clickCounter);
    }
  }
});

3.В шаблоне указать свойство для получения пользовательских кнопок, а также зарегистриовать пользовательское действие.

<h3>{{header}}</h3>

<div class="row">
  {{flexberry-objectlistview
    // ...
    customButtons=customButtons
    userButtonActionTest='userButtonActionTest'
  }}
</div>

Инструменты работы с объектами на списках

Кнопки “Отметить все на текущей странице”, “Отметить все на всех страницах” и “Установить сортировку по умолчанию” активируются вместе с checkbox в строках параметром showCheckBoxInRow.

  • “Отметить все на текущей странице” - отмечает все объекты на сранице, добавляет отмеченые объекты в slectRecords.
  • “Отметить все на всех страницах” - активирует параметр allSeclect, обработка удаления при активации этого параметра реализуется в соответствии с потребностями конкретного приложения в action delete() компонента.
  • “Установить сортировку по умолчанию” - устанавливает сортировку и количество отображаемых страниц по умолчанию.

Настройка иерархического списка

Если список является иерархическим (у объекта есть ссылка на самого себя), то иерархия для списка установлена по умолчанию.

Если иерархию для списка необходимо отключить, то в шаблоне следует прописать disableHierarchicalMode = true.

Если в модели есть две или больше ссылки на себя (по которым может быть иерархия), то нужно указать имя той по которой должна быть иерархия: hierarchyByAttribute = propertyName.

Блокирование отдельных ячеек списка

На списке существует возможность заблокировать отдельную ячеку для открытия объекта на редактирование, оставив при этом активным клик на строке.

Для этого чтобы выключить клик по строке, нужно переопределить переход к форме редактирования, используя параметр (params):

params.goToEditForm = false;

Затем вызвать метод _super.

В параметрах обработчика клика по строке есть:

  • запись, по которой кликнули
  • колонка по которой кликнули (в ней есть имя свойства, заголовок колонки на форме, cellComponent этой колонки)
  • индекс нажатой колонки.

Данные параметры используются для отключения обработки клика по строке при определенных условиях (т.е. при клике по определенным ячейкам).

Например:

actions: {
    objectListViewRowClick(record, params) {
      if (params.column && params.column.cellComponent.componentName === 'flexberry-file' && params.originalEvent.target.tagName.toLowerCase() !== 'td') {
        params.goToEditForm = false;
      }

      this._super(...arguments);
    }

Подробнее в коде приложения dummy.

Вычислимые свойства в getCellComponent

Чтобы создать вычисляемое свойство нужно, в controllers, в getCellComponent добавить свойство computedProperties: { thisController: this }:

getCellComponent(attr, bindingPath, model) {
   let cellComponent = this._super(...arguments);
   if (attr.kind === 'belongsTo') {
     cellComponent.componentProperties = {
       choose: 'showLookupDialog',
       remove: 'removeLookupValue',
       displayAttributeName: 'name',
       required: true,
       relationName: 'author',
       projection: 'ApplicationUserL',
       autocomplete: true,
       computedProperties: { thisController: this },
       readonly: false,
      };
   }

   return cellComponent;
 },

Таким образом в свойстве computedProperties у текущего controller-а будет this из dynamic-properties со всеми своими observer-ами. Теперь чтобы поменять любое из свойств встраимого компонента достаточно изменить значение в computedProperties:

checkboxValue: false,

lookupReadonly: Ember.observer('checkboxValue', function() {
  if (!Ember.isNone(this.get('computedProperties.dynamicProperties.readonly'))) {
    if (this.get('checkboxValue')) {
      this.set('computedProperties.dynamicProperties.readonly', true);
    } else {
      this.set('computedProperties.dynamicProperties.readonly', false);
    }
  }

  return this.get('checkboxValue');
}),