2015-08-21 2 views
1

В моем текущем проекте я хотел бы иметь возможность создавать новые объекты при поиске ссылочного объекта. Это происходит в нескольких местах приложения.Создание новых записей при поиске ссылочного объекта

Например, предположим, что у нас есть City Entity и Country Entity. У муниципального образования есть обязательная ссылка на страну.

В моем случае использования я хотел бы создать новый Город. Когда я это сделаю, мне придется назначить страну новому городу. Когда я нажимаю значок поиска, я получаю диалог выбора со всеми существующими странами. Но если у меня нет страны, которую я хочу, мне нужно прекратить операцию, вернуться в список стран и создать новую, которую я бы хотел назначить своему новому городу.

  1. Можно ли создать эту новую страну из диалога выбора со всеми странами?
  2. Если возможно, добавляется ли страна в список сразу после его создания?
  3. Можно ли определить диапазон для списка стран? Например, показаны только страны Европы, если пользователь находится в Европе.

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

ответ

3

Настройка диалога LOV:

Вы можете легко настроить диалог LOV, создав свой собственный класс действия LOV, который установлен рядом с эталонными полей.

  • Добавление нового действия в диалоговом окне (создавание действие):
public class LovActionWithCreate<E, F, G> extends LovAction<E, F, G> { 

    private IDisplayableAction createAction; 

    @Override 
    protected void feedContextWithDialog(IReferencePropertyDescriptor<IComponent> erqDescriptor, 
             IQueryComponent queryComponent, IView<E> lovView, IActionHandler actionHandler, 
             Map<String, Object> context) { 
    super.feedContextWithDialog(erqDescriptor, queryComponent, lovView, actionHandler, context); 
    List<IDisplayableAction> defaultLovDialogActions = (List<IDisplayableAction>) context.get(
     ModalDialogAction.DIALOG_ACTIONS); 
    defaultLovDialogActions.add(1, getCreateAction()); 
    } 

    /** 
    * Gets create action. 
    * 
    * @return the create action 
    */ 
    protected IDisplayableAction getCreateAction() { 
    return createAction; 
    } 

    /** 
    * Sets create action. 
    * 
    * @param createAction 
    *  the create action 
    */ 
    public void setCreateAction(IDisplayableAction createAction) { 
    this.createAction = createAction; 
    } 
} 

Ключевым моментом является то, чтобы переопределить метод feedContextWithDialog для того, чтобы установить новое действие в диалоговом окне.

Следующий шаг - установить новое действие LOV. Вы можете сделать это глобально для всего приложения или на опорной точки зрения:

  • заменить действие LOV глобально это всего лишь вопрос того, чтобы объявить акцию под названием 'lovAction' в приложение frontend.groovy, а именно:
action('lovAction', parent: 'lovActionBase', class:'test.LovActionWithCreate', 
    custom: [createAction_ref:'theCreateAction'] 
) 
  • заменив действие LOV на определенном опорное поле в форме может быть сделан с помощью referencePropertyViewform или в table) и его свойство «lovAction», например,:
action('lovActionWithCreate', parent: 'lovActionBase', class:'test.LovActionWithCreate', 
    custom: [createAction_ref:'theCreateAction'] 
) 

form('ACertainForm'){ 
    fields { 
    ... 
    referencePropertyView name:'country', lovAction:'lovActionWithCreate' 
    ... 
    } 
} 

Создание сущности в диалоге LOV:

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

  • Прежде всего, мы должны открыть новое диалоговое окно.

Для этого мы наследуем встроенный EditComponentAction. Цель этого действия - отредактировать модель в модальном диалоге. Единственная трудность здесь заключается в том, что наша модель известна только во время работы. Нет проблем, хотя мы будем использовать динамический характер Jspresso.

public class CreateEntityFromLOVAction<E, F, G> extends EditComponentAction<E,F,G> { 

    @Override 
    protected Object getComponentToEdit(Map<String, Object> context) { 
    IEntityFactory entityFactory = getBackendController(context).getEntityFactory(); 
    IQueryComponent lovQueryComponent = (IQueryComponent) context.get(IQueryComponent.QUERY_COMPONENT); 
    Class<IEntity> entityToCreateContract = lovQueryComponent.getQueryContract(); 

    IEntity entityInstance = entityFactory.createEntityInstance(entityToCreateContract); 
    setActionParameter(Arrays.asList(entityInstance), context); 
    return entityInstance; 
    } 

    @Override 
    protected IViewDescriptor getViewDescriptor(Map<String, Object> context) { 
    IEntityFactory entityFactory = getBackendController(context).getEntityFactory(); 
    IQueryComponent lovQueryComponent = (IQueryComponent) context.get(IQueryComponent.QUERY_COMPONENT); 
    Class<IEntity> entityToCreateContract = lovQueryComponent.getQueryContract(); 
    IComponentDescriptor<?> entityToCreateDescriptor = entityFactory.getComponentDescriptor(entityToCreateContract); 

    BasicComponentViewDescriptor formViewDescriptor = new BasicComponentViewDescriptor(); 
    formViewDescriptor.setModelDescriptor(entityToCreateDescriptor); 
    return formViewDescriptor; 
    } 
} 

Если вы посмотрите на код выше, наше новое действие заботится о следующих:

  1. Получить тип объекта, чтобы создать из контекста. Для этого мы просто изучаем компонент запроса, который является моделью диалога LOV.
  2. Создайте экземпляр сущности и установите его как параметр действия в контексте, чтобы цепочка продолжала работать над ним (сохранить, закрыть диалог).
  3. Создайте форму для отображения в диалоговом окне создания.

Точки 1 и 2 обрабатываются методом getComponentToEdit и пунктом 3 методом getViewDescriptor.

  • Затем, когда пользователь нажимает Ok, мы должны сохранить объект, добавить его в список результатов LOV и закрыть диалоговое окно создания.

Для этого мы создадим новое действие и подключим его к saveAction и closeDialogAction встроенным действиям.

public class CreateEntityFromLOVPersistAction<E, F, G> extends FrontendAction<E,F,G> { 

    @Override 
    public boolean execute(IActionHandler actionHandler, Map<String, Object> context) { 
    if (super.execute(actionHandler, context)) { 
     IQueryComponent lovQueryComponent = (IQueryComponent) context.get(IQueryComponent.QUERY_COMPONENT); 
     List<IEntity> createdEntityInstance = getActionParameter(context); 

     lovQueryComponent.setQueriedComponents(createdEntityInstance); 
     return true; 
    } 
    return false; 
    } 
} 
  • И последняя проводка в SJS frontend.groovy:
action('createEntityFromLovOkAction', parent: 'okDialogFrontAction', 
     class:'test.CreateEntityFromLOVPersistAction', 
     wrapped: 'saveBackAction', next: 'closeDialogAction') 

action('createEntityFromLovAction', parent: 'editComponentAction', 
     class: 'test.CreateEntityFromLOVAction', 
     name:'add.name', custom: [ 
      okAction_ref: 'createEntityFromLovOkAction' 
     ] 
) 

action('lovAction', parent: 'lovActionBase', 
     class:'test.LovActionWithCreate', 
    custom: [createAction_ref:'createEntityFromLovAction'] 
) 

Длинный ответ менее чем 100 строк кода, но теперь у вас есть полностью общие действия LOV, где пользователь может создайте любые отсутствующие основные данные, не покидая его текущего экрана.

Предустановка некоторые данные в LOV фильтра в зависимости от контекста пользователя:

Для этого, мы обычно используем отображениеинициализации, которая позволяет установить некоторые ограничения (либо статические или динамические) на эталонном собственности когда он запрашивается в LOV.Например, давайте рассмотрим следующий случай использования:

  • У вас есть 2 сущностей, Contract и Tariff, которые связаны друг с другом через отношения 1-N, т.е. Contract связан с 1 Tariff.
  • Contract и Tariff оба имеют country свойство и Tariff может быть назначен Contract тогда и только тогда, когда они принадлежат к одной и той же стране.
  • Tarrif имеет свойство status и может использоваться только в Contract, если его status является ACTIVE.

Вы можете просто применять эти правила в LOV, установив отображение инициализации на опорном собственности следующим образом:

Entity('Contract', ...) { 
    ... 
    reference 'tariff', ref: 'Tariff', 
     initializationMapping: [ 
      'country': 'country', 
      'status': 'ACTIVE' 
     ] 
    ... 
} 

Думая об этом, такое поведение может очень хорошо найти его путь к структуре, поэтому, пожалуйста, не стесняйтесь использовать запрос расширения в Jspresso GitHub.

+0

Hi Vincent, Всего комментариев: Я добавил это поведение в свое приложение, как вы изящно объяснили в своем ответе. Оно работало завораживающе. Спасибо. – Weggyboy

+0

Стандартное действие LOV было улучшено, чтобы включить эту функциональность в предстоящий Jspresso 4.3. См. [Этот вопрос Github] (https://github.com/jspresso/jspresso-ce/issues/41) –

Смежные вопросы