Tony60
Giga Guru

Use Case

We wanted to render the catalog item widget (widget-sc-cat-item-v2) dynamically depending on which button is clicked. When the User modified any values on the form, a popup needs to appear that the user actively confirms that modified data will be lost.

Out of the box solution

 The popup should be similar to the OOTB functionality when leaving a catalog item page with modified values

find_real_file.png

This popup is not triggered when dynamically rendering the widgets using the "sp-widget" directive, because we are not changing the portal page.

Solution

To detect user changes when switching widgets, we need to use the "spModel.gForm.rendered" event to initialize the "g_form" instance. Then, when changing the widgets, we can use the function "g_form.isUserModified()" to check if the user has made any changes.

We cannot use the "field.change" event, because it is also triggered on form load, when default values are set by the system.

When the user now modfied a value and changes the Catalog Item, he is prompted the following

find_real_file.png

Widget Source Code

Widget Client Controller
function($scope, $rootScope, spModal) {
  /* Widget controller */
  var c = this;

  // Set g_form variable
  var g_form = "";
  // Initialize user modification variable with false
  var userModified = false;

  /**
   * Event Listener to check when the form has rendered
   * Set g_form value to gFormInstance
   */
  $rootScope.$on('spModel.gForm.rendered', function (e, gFormInstance) {
	// Reset value
	userModified = false;
	  
    g_form = gFormInstance;
  });

  /**
   * Load Widget function. This function is dynamically triggered if a user clicks a button
   * @param {string} _catItemId System-ID of Catalog Item to Render
   */
  c.renderCatalogItem = function (_catItemId) {
    // Magic happens here, make sure the function is defined and set the userModified boolean
    if(typeof g_form.isUserModified == "function" && g_form.isUserModified()){
        userModified = true;
    }
  
    // Set action for server script and catalog item to load
    c.data.action = "renderCatItemWidget";
    c.data.catItemToLoad = _catItemId;

    // If user modified values, open a prompt that the user validates leaving the form
    if (userModified == true) {
      spModal.open({
        title: '${Leave form?}',
        message: '${Changes you made will be lost.}'
      }).then(function (confirmed) {
        c.server.update().then(function () {
          // Reset variables
          c.data.action = undefined;
          c.data.catItemToLoad = undefined
        });
      })
    } else {
      c.server.update().then(function () {
        // Reset variables
        c.data.action = undefined;
        c.data.catItemToLoad = undefined
      });
    }
  }
}

Server script

(function() {
    /* populate the 'data' object */
    /* e.g., data.table = $sp.getValue('table'); */
    
	// We need to build an array, otherwise it won't render dynamically
    data.widgetArr = [];

    if (input && input.action) {
        var action = input.action;

        if (action == "renderCatItemWidget") {
            // Set sys_id of catalog item to widget options
            var widgetOptions = {
                "sys_id": input.catItemToLoad
            };
            
			var widget = $sp.getWidget("widget-sc-cat-item-v2", widgetOptions);

            data.widgetArr.push(widget);
        }
    }
})();
Body HTML Template
<div>
  <button ng-click="c.renderCatalogItem('SYSTEM-ID OF CAT ITEM')">First Catalog Item</button>
  <button ng-click="c.renderCatalogItem('SYSTEM-ID OF CAT ITEM')">Second Catalog Item</button>
</div>

<!-- We need to iterate threw widget array, otherwise it won't render dynamically -->
<div ng-if="c.data.widgetArr && c.data.widgetArr.length > 0" ng-repeat="w in c.data.widgetArr">
    <sp-widget widget="w"></sp-widget>
</div>
Version history
Last update:
‎05-14-2020 01:32 AM
Updated by: