- 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-08-2018 11:38 AM
looks good. also if you want your tabs to be scrollable, I used this as a dependency: https://github.com/VersifitTechnologies/angular-ui-tab-scroll
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-08-2018 04:04 PM
Okay Im a little closer now.
To filter the list (ng-repeat), I had to create a custom filter.
This thread here shows how to create a custom AngularJS filter for Service Portal:
https://community.servicenow.com/community?id=community_blog&sys_id=269caee1dbd0dbc01dcaf3231f961940&view_source=searchResult
Here is the revised code:
<uib-tab index="$index+1" ng-repeat="titleContainer in containers | titledFormSectionFilter" heading="{{titleContainer.captionDisplay}}">
Here is the custom UI Script for the custom AngularJS filter:
(function() {
angular.module('myTabbedFormFilters', []).filter('titledFormSectionFilter', function() {
return function(input) {
var output = [];
for (var i = 0; i < input.length; i++) {
if (input[i].captionDisplay.length > 0) {
output.push(input[i]);
}
}
return output;
};
});
})();
And here is the result:
- 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-08-2018 07:02 PM
giving this a try now, thanks james! for the UI Script, did you have to name it anything specific?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-08-2018 07:16 PM
Got it to work @jamesmcwhinney!! this is awesome, thanks!