[ELMA3] Кастомные формы задач
Любые задачи в системе ELMA имеют форму представления по умолчанию. Она генерируется автоматически. В большинстве случаев стандартные формы представления бывают удобны. К тому же при внедрении системы не требуется тратить время на их создание. Однако иногда требуется отображать задачи иным образом, когда необходима разметка страницы, отличная от стандартной. В этом случае используются кастомные формы задач. Кастомные формы могут быть созданы не только для задач, но и для документов, объектов CRM и других объектов системы.
В этой статье мы подробно остановимся на том, как можно создать свою собственную форму задачи в бизнес-процессе.
Для начала необходимо создать файл *.cshtml в папке ...\ELMA3-Standart(Express)\UserConfig\WebApplication. Более подробно о создании и месторасположении файла описано здесь.
Теперь открываем файл в любом текстовом редакторе.
Так как формы создаются с помощью разметки .Net Razor, мы можем использовать HTML-разметку при создании формы.
Чтобы создать новую форму задачи в процессе необходимо ввести следующее пространство имён:
@using EleWise.ELMA.BPM.Web.Tasks.Models
@using (var data = new ObjectViewData(this, Model.Entity)) { }
где:
@using EleWise.ELMA.BPM.Web.Tasks.Models – необходимо для отображения задачи в процессе
@using (var data = new ObjectViewData(this, Model.Entity)) – необходимо для правильного отображения переменных и корректной работы скриптов в ELMA
Вся остальная разметка выполнятся между фигурных скобок.
Рассмотрим основные примеры отображения контекстных переменных на форму:
@Html.Caption – название добавляемого поля
@Html.EditorOrDisplay – добавление редактируемого поля
@Html.Display – добавление нередактируемого поля
@Html.EditableProperty – вывод атрибута с названием
@Html.Property – вывод переменной в режиме «Только для чтения»
@Html.Editor - вывод поля редактирования (без названия).
("Entity.<название атрибута>", a => {}) – добавление самого поля
Переменная типа "блок" отображается так же, как и остальные контекстные переменные:
@Html.EditableProperty("Entity.blok")
При этом можно выводить не все свойства блока, а только добавленные в контекст этой задачи, делается это так:
@Html.TableFormStart()
@Html.Property("Entity.blok", a => {
a.TablePartParentId = Model.Entity.Id;
a.ViewProviderUid = EleWise.ELMA.Workflow.Web.Integration.WorkflowTaskObjectViewItemProvider.UID;
a.ViewItemId = Model.Task.Id.ToString();
})
@Html.TableFormEnd()
Ниже приведён пример кастомной формы задачи:
Рис. 1. Пример кастомной формы задачи
В этом примере реализованы:
- Раскрывающийся список.
- Разметка полей и названия атрибутов.
- Таблица, при заполнении которой динамически подсчитывается итог.
- Раскрывающийся список:
@(Html.CollapsiblePanel() // добавляем раскрывающийся список
.Id(ViewData.TemplateInfo.GetFullHtmlFieldId("FIO")) // присваиваем ей ID ("FIO")
.Header(SR.T("ФИО")) //указываем название панели, а так же будет ли сохраняться раскрытие панели или нет .SaveState(false)
.Class("Gray_Input_Separator") // указываем цвет панели
.Expanded(true)
.Content(@<text>
</text>).Render()) // закрывающие теги раскрывающегося списка
Внимание!
Для того чтобы автоматически получить Итог (использовано в нашем примере на рисунке 1 выше), достаточно написать сценарий в ELMA и в дальнейшем указать его на свойствах, при изменении которых будет срабатывать метод.
public virtual void OnChangeItog (Context context, EleWise.ELMA.Model.Views.FormViewBuilder<Context> form)
{
context.I1 = context.K1*context.S1;
context.I2 = context.K2*context.S2;
context.Itog= context.I1+context.I2;
}
То есть те сценарии, которые работают в стандартной форме, будут работать и с разметкой Razor при условии, что добавлено:
@using (var data = new ObjectViewData(this, Model.Entity))
Окончательный вариант выглядит так:
@using EleWise.ELMA.BPM.Web.Tasks.Models
@using EleWise.ELMA.Web.Mvc.Html.Forms
@{
var onChangeScriptName = "OnChangeItog(EleWise.ELMA.Model.Entities.ProcessContext.P_111,
EleWise.ELMA.Model.Views.FormViewBuilder`1[[EleWise.ELMA.Model.Entities.ProcessContext.P_111]]) - OnChangeItog(Context context, FormViewBuilder<Context> form)";
}
@using (var data = new ObjectViewData(this, Model.Entity))
{
@(Html.CollapsiblePanel()
.Id(ViewData.TemplateInfo.GetFullHtmlFieldId("FIO"))
.Header(SR.T("ФИО"))
.SaveState(false)
.Class("Gray_Input_Separator")
.Expanded(true)
.Content(@<text>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td style="width: 50%;">
<div class="table-form-container" >
<table class="table-form table-ColumnItem">
<tbody>
<tr hidecount="0">
<td class="table-SingleColumnItem" colspan="2">
@Html.TableFormStart()
@Html.EditableProperty("Entity.Familiya")
@Html.EditableProperty("Entity.Imya")
@Html.EditableProperty("Entity.Otchestvo")
@Html.TableFormEnd()
</td>
</tr>
</tbody>
</table>
</div>
</td>
<td style="width: 50%;">
<div class="table-form-container">
<table class="table-form table-ColumnItem">
<tbody>
<tr hidecount="0">
<td class="table-SingleColumnItem" colspan="2">
@Html.TableFormStart()
@Html.EditableProperty("Entity.Blok")
@Html.TableFormEnd()
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</text>).Render())
@(Html.CollapsiblePanel()
.Id(ViewData.TemplateInfo.GetFullHtmlFieldId("Table"))
.Header(SR.T("Таблица"))
.SaveState(true)
.Class("Gray_Input_Separator")
.Expanded(false)
.Content(@<text>
<div style="padding: 10px;">
<table id="@(ViewData.TemplateInfo.GetFullHtmlFieldId("TableComponent"))">
<tbody>
<tr>
<td class="table-title">
</td>
<td class="table-title">
<P>Количество</P>
</td>
<td class="table-title">
<P>Сумма</P>
</td>
<td class="table-title">
<P>Итог</P>
</td>
</tr>
<tr>
<td class="table-title">
<P>1</P>
</td>
<td>
@Html.Editor("Entity.K1", a => {
a.OnChangeScriptName = onChangeScriptName;
})
</td>
<td>
@Html.Editor("Entity.S1", a => {
a.OnChangeScriptName = onChangeScriptName;
})
</td>
<td id="@(ViewData.TemplateInfo.GetFullHtmlFieldId("Entity.I1"))_ValueContainer">
@Html.Editor("Entity.I1", a => {})
</td>
</tr>
<tr>
<td class="table-title">
<P>2</P>
</td>
<td>
@Html.Editor("Entity.K2", a => {
a.Container("div");
a.OnChangeScriptName = onChangeScriptName;
})
</td>
<td>
@Html.Editor("Entity.S2", a => {
a.Container("div");
a.OnChangeScriptName = onChangeScriptName;
})
</td>
<td id="@(ViewData.TemplateInfo.GetFullHtmlFieldId("Entity.I2"))_ValueContainer">
@Html.Editor("Entity.I2", a => {})
</td>
</tr>
<tr>
<td align="right" colspan="3" class="itog-td">
<b>Итог:</b>
</td>
<td id="@(ViewData.TemplateInfo.GetFullHtmlFieldId("Entity.Itog"))_ValueContainer">
@Html.Editor("Entity.Itog", a => { })
</td>
</tr>
</tbody>
</table>
</div>
</text>).Render())
}
<style>
#TableComponent .itog-td {
vertical-align: middle;
padding-right: 6px;
}
#TableComponent,
#TableComponent th,
#TableComponent td {
border: 1px solid #d0d5da;
}
#TableComponent .table-title {
background: #cbe2ff;
padding: 8px 6px;
}
</style>