- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-01-2018 01:48 PM
I have cloned the ootb widget-form and am attempting to make edits to the template in order to make the widget-form tabular. I am running into an issue where form sections and any splits within a section are considered the same thing. For example, in the system view, I have a form section that looks like this:
Notice that in my form section called "Name" I have two fields in 1 column format, then I split, and have 6 remaining fields in a two column format. When I pull up the formModel for the widget-form, I see this:
"_sections":[
{
"_bootstrap_cells":12,
"_count":1,
"visible":true,
"columns":[
{
"fields":[
{
"name":"name",
"type":"field"
},
{
"name":"favorite_fruit",
"type":"field"
},
{
"name":"birth_date",
"type":"field"
}
]
}
],
"caption":"Name",
"id":"136ae5c5db030300b11c771c8c9619a0",
"scope_name":"x_82643_my_custom"
},
{
"_bootstrap_cells":6,
"_count":2,
"visible":true,
"columns":[
{
"fields":[
{
"name":"name.phone",
"type":"field"
},
{
"name":"name.city",
"type":"field"
},
{
"name":"name.country",
"type":"field"
}
]
},
{
"fields":[
{
"name":"name.email",
"type":"field"
},
{
"name":"name.employee_number",
"type":"field"
},
{
"name":"name.gender",
"type":"field"
}
]
}
],
"caption":"",
"id":"",
"scope_name":"x_82643_my_custom"
}
]
Even though they appear on the same form section, the formModel recognizes both as individual sections. This matters because when I change the template to be tabular, I'm creating the tabs via ng-repeat on containers:
<uib-tabset active="active" justified="true">
<uib-tab index="$index+1" ng-init="$last ? execItemScripts() : null" ng-show="isContainerVisible(container)" ng-repeat="container in containers" heading="{{$index+1}}. {{container.captionDisplay || container.caption}}">
When this runs, the widget-form creates two tabs: 1 with a tab name of "Name" and a subsequent one is just blank:
I want all that information to be in one tab, like it appears in the system view.
I've found the code in the spModel directive where I think this problem stems from, but am unsure how to alter it so that all the fields appear under one section:
function getNestedFields(fields, containers) {
if (!containers)
return;
for (var _container in containers) {
var container = containers[_container];
if (container.columns) {
for (var _col in container.columns) {
var col = container.columns[_col];
for (var _field in col.fields) {
var field = col.fields[_field];
if (field.type == "container")
getNestedFields(fields, [field]);
else if (field.type == "checkbox_container")
getNestedFields(fields, field.containers);
else if (field.type == "field")
fields.push(formModel._fields[field.name]);
}
}
}
}
}
Any suggestions on how to change this code so that _sections without a "caption" or "id" gets appended to the previous _section?
Thanks.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-08-2018 04:21 PM
Ok ive got it.
Here is the template XML:
<div>
<uib-tabset active="active" justified="true">
<uib-tab index="$index+1" ng-repeat="titleContainer in containers | titledFormSectionFilter" heading="{{titleContainer.captionDisplay}}">
<fieldset ng-repeat="container in containers | currentFormSectionFilter : titleContainer.captionDisplay" ng-show="isContainerVisible(container)" ng-init="$last ? execItemScripts() : null">
<legend class="h4" ng-if="(container.caption || container.captionDisplay)">{{container.captionDisplay || container.caption}}</legend>
<div class="row">
<div ng-repeat="column in container.columns" class="col-md-{{12 / container.columns.length }}">
<div ng-switch="f.type" ng-repeat="f in column.fields" id="{{getVarID(f)}}" ng-class="{'form-inline': isInlineForm === true }">
<div ng-switch-when="label" ng-if="formModel._fields[f.name]" ng-show="formModel._fields[f.name].visible">
<label ng-bind-html="::f.label"></label>
<span ng-if="::formModel._fields[f.name].instructions" ng-bind-html="::formModel._fields[f.name].instructions"></span>
<p ng-if="::formModel._fields[f.name].help_text" title="{{::formModel._fields[f.name].help_tag}}" class="help-block" ng-bind-html="::formModel._fields[f.name].help_text"></p>
<hr class="sp_label_hr"></hr>
</div>
<sp-form-field ng-switch-when="field" ng-if="formModel._fields[f.name]" form-model="formModel" field="formModel._fields[f.name]" glide-form="getGlideForm()" ng-show="formModel._fields[f.name].visible"></sp-form-field>
<sp-variable-layout ng-switch-when="container" ng-init="containers=[f]"></sp-variable-layout>
<sp-variable-layout ng-switch-when="checkbox_container" ng-init="containers=f.containers"></sp-variable-layout>
<sp-widget ng-switch-when="formatter" ng-if="formModel._formatters[f.id].widgetInstance" widget="formModel._formatters[f.id].widgetInstance" page="{g_form: getGlideForm()}"></sp-widget>
<hr ng-switch-when="break"></hr>
</div>
</div>
</div>
</fieldset>
</uib-tab>
</uib-tabset>
</div>
and here is the UI script for the custom AngularJS formatters (there are two):
(function() {
angular.module('myTabbedFormFilters', []).filter('titledFormSectionFilter', function() {
return function(input) {
var output = [];
console.log('JMM: input.length: '+ input.length);
for (var i = 0; i < input.length; i++) {
if (input[i].captionDisplay.length > 0) {
console.log('JMM: captionDisplay:' + input[i].captionDisplay);
output.push(input[i]);
}
}
return output;
};
}).filter('currentFormSectionFilter', function() {
return function(input, startingCaptionDisplay) {
var output = [];
var include = false;
for (var i = 0; i < input.length; i++) {
if (input[i].captionDisplay == startingCaptionDisplay) {
include = true;
output.push(input[i]);
} else if((include)&&(input[i].captionDisplay == '')){
output.push(input[i]);
} else {
include = false;
}
}
return output;
};
});
})();
And here is the result:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-07-2018 08:29 AM
Hi Davilu,
Thanks for bringing up this discussion.
Currently we are in a phase of doing the same where we have to convert the new section separators into tabs in the 'Form-widget' as they are shown in the actual form.
Were you able to get through in updating the 'Form-widget' template ?
It would be great if you could please let us know how you were able to crack it.
Thanks in advance.
Regards,
Surendar M
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-07-2018 03:29 PM
We are looking to do this as well.
Have you had any luck?
Thanks!
- James
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-08-2018 11:00 AM
Hi @surendarm and @jamesmcwhinney, so far I haven't had any luck in rectifying the empty tab issue. Will update the group once I get it working. If you guys have a break through, please share as well! Thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-08-2018 11:20 AM
Thanks to your code and to this post here (https://community.servicenow.com/community?id=community_article&sys_id=955c66a1dbd0dbc01dcaf3231f9619e4) and @Dylan.lindgren I am almost caught up to you I think.
So far I have:
1. Cloned the widget 'widget-form'
2. Cloned the page 'Form' and updated it to use my custom widget.
3. Updated my custom 'widget-form' to refer to a custom template :
<!-- form -->
<div>
<sp-model form_model="data.f" mandatory="mandatory" template-url="smse-tabbed-sp-model-xml"></sp-model>
</div>
4. Created a custom sp_ng_template "smse-tabbed-sp-model-xml" with the following code:
<div>
<uib-tabset active="active" justified="true">
<uib-tab index="$index+1" ng-show="isContainerVisible(container)" ng-repeat="container in containers" heading="{{$index+1}}. {{container.captionDisplay || container.caption}}">
<fieldset ng-repeat="container in containers" ng-show="isContainerVisible(container)" ng-init="$last ? execItemScripts() : null">
<legend class="h4" ng-if="(container.caption || container.captionDisplay)">{{container.captionDisplay || container.caption}}</legend>
<div class="row">
<div ng-repeat="column in container.columns" class="col-md-{{12 / container.columns.length }}">
<div ng-switch="f.type" ng-repeat="f in column.fields" id="{{getVarID(f)}}" ng-class="{'form-inline': isInlineForm === true }">
<div ng-switch-when="label" ng-if="formModel._fields[f.name]" ng-show="formModel._fields[f.name].visible">
<label ng-bind-html="::f.label"></label>
<span ng-if="::formModel._fields[f.name].instructions" ng-bind-html="::formModel._fields[f.name].instructions"></span>
<p ng-if="::formModel._fields[f.name].help_text" title="{{::formModel._fields[f.name].help_tag}}" class="help-block" ng-bind-html="::formModel._fields[f.name].help_text"></p>
<hr class="sp_label_hr"></hr>
</div>
<sp-form-field ng-switch-when="field" ng-if="formModel._fields[f.name]" form-model="formModel" field="formModel._fields[f.name]" glide-form="getGlideForm()" ng-show="formModel._fields[f.name].visible"></sp-form-field>
<sp-variable-layout ng-switch-when="container" ng-init="containers=[f]"></sp-variable-layout>
<sp-variable-layout ng-switch-when="checkbox_container" ng-init="containers=f.containers"></sp-variable-layout>
<sp-widget ng-switch-when="formatter" ng-if="formModel._formatters[f.id].widgetInstance" widget="formModel._formatters[f.id].widgetInstance" page="{g_form: getGlideForm()}"></sp-widget>
<hr ng-switch-when="break"></hr>
</div>
</div>
</div>
</fieldset>
</uib-tab>
</uib-tabset>
</div>
which gives me the below:
and now I am running up against the same problem..
..How to get the containers to consolidate properly like they do in the regular UI.