The CreatorCon Call for Content is officially open! Get started here.

Changing widget-form template to be tabbed

davilu
Mega Sage

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:

find_real_file.png

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:

find_real_file.png

  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.

1 ACCEPTED SOLUTION

jamesmcwhinney
Giga Guru

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:

find_real_file.png

 

find_real_file.png

 

 

 

 

View solution in original post

27 REPLIES 27

surendarm
Kilo Expert

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

jamesmcwhinney
Giga Guru

We are looking to do this as well.

Have you had any luck?

 

Thanks!

- James

davilu
Mega Sage

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!

jamesmcwhinney
Giga Guru

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:

find_real_file.png

 

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.