Dynamically Hiding Service Request Activity Form Fields in the Cireson Portal

Hello team, me again. Today I’m going to be discussing a quick customization for the Cireson Portal around Activities, but first lets talk a little about how activities work in the portal.

Activities in the portal, like in Service Manager, are more like second class citizens. They are there, they are useful and do a lot of hard work, but they don’t really get appreciated or show the love of having their very own form. This is fine, and has the benefit of making the workflow feel more a part of the parent work item, but has the disadvantage of making the activity forms themselves difficult to customize.

While this will most likely be resolved in a future version of the portal, we have a problem today that we must solve. That is that we want to hide certain fields on the activity forms to make them easier to understand and remove the unnecessary clutter of fields we aren’t using.

In order to accomplish this we are going to once again call on my good friend the custom.js file. If you are unfamiliar with this, it is the javascript file that sits in the CustomSpace folder of the portal and is loaded on every form page in the background. This file lets us manipulate the portal in all sorts of fun and interesting ways!

Let’s get started. The first thing we need to do is understand how the activities work in the portal as mentioned above. The activity forms are sub-forms of the SR/IR/CR forms in the portal. So they are dynamically generated from code each time you load a parent work item form. This keeps us from modifying the activity template as we would the parent forms, so we will need another approach here.

Adding to the difficulty of this task is the fact that the activities are actually loaded into the form AFTER the rest of the form is loaded. This means we can’t simply run our script to hide the fields on load, we have to wait for the activities to finish despite the fact the page itself has already loaded. This is mostly transparent to the end user when clicking through the form, but very obvious when running code at near the speed of light.

Our Solution

For my solution I’ve decided that I want to apply the changes to the activity forms when the user is going to actually use those forms, so that means that he’s clicking on the Activity tab. Keep in mind as we go through this that this solution has not been fully tested and I look forward to your feedback on any problems you encounter.

Here is what our function will look like in the custom.js file:

//start hide activity fields
app.custom.formTasks.add('ServiceRequest', null, function(formObj, viewModel){  
      formObj.boundReady(function () {
            var targetFields = [
                  "Area",
                  "Priority",
                  "Stage",
                  "Scheduled Start",
                  "Scheduled End",
                  "Impacted Configuration Items"
            ]
            
            fn_HideActivityFields(targetFields);
      });
});
      
function fn_HideActivityFields (fields) {
    $("a[data-cid=Activities").on("click", function (){
        console.log("I'm hiding fields!", fields);
        for(var i=0; i < fields.length; i++){
                var label = fields[i];
                var item = $("div.activity-item-form").find("label span:contains(" + label + ")");
                $(item).each(function () {
                    var ctrl = $(this).parents("div")[2];
                    $(ctrl).hide();
                });
        }  
    });
}
//END hide activity fields

Now let’s talk through this, one function at a time.

2016-02-17_15-49-15

Our first function is simply the ‘task’ construct that is given to us by the Cireson Dev team. This is designed to make it easy to load custom tasks within the work item forms. We are using this construct and abusing it a little bit to make the action happen on load, rather than requiring the user to click any particular button. That is accomplished by using a NULL as the second value in the function call.

As the third value we are passing a function ourselves and this is what will actually be run when the task runs on form load. We are passing both the viewModel (work item data) and the formObj (the document object) into the function to make it easy to work with.

We are then binding our own function to the ‘boundReady’ function of the formObj. This will run our script only after the form has finished loading. Without waiting for this, the activities tab might not even exist when we try and bind our function to it.

When then define an array of the target field names that we want to hide for the activities. This is the same as you see on the label for the activity field when viewing them in the portal.

Finally, we pass this array into our custom function, which is where we will do all the work to hide the fields. Let’s look at that function now.

2016-02-17_15-49-32

This one looks a little more involved but it’s actually really quite simple. Let’s walk through it line by line.

The first thing we do is use a jQuery call $() to find the Activities tab element in the page, and then bind a function of our own to the ‘click’ event. The second parameter is our function itself. This will be run whenever a user clicks the Activities tab.

Next, we have a simple console log command to let us know that the function is running successfully when the tab is clicked.

We then have a FOR loop that loops through our activity fields array, checking each of items in the array against our page. Within this loop we set a LABEL variable just to make it easy to work with the current field. Then we use jQuery to find those labels that match within the page.

Looking at that array of elements using jQuery again we run a custom function on each of them. This function looks at the element and then steps backwards to find the parent DIV that will hide both the label and the input field of our activity field we want to hide.

Finally, we use jQuery to hide this field.

We do this for each item in our array and check it against each matching element in the page, hiding all of them. That takes this:

2016-02-17_16-02-57

And turns it into this:

2016-02-17_16-03-30

Hope that helps! Let me know what issues you find and we can make that a learning experience for all of us as well. Thanks for reading.

5 thoughts on “Dynamically Hiding Service Request Activity Form Fields in the Cireson Portal

  1. I was expecting to be able to copy the code above into our empty custom.js file and have the customisation display immediately after restarting the website. I can see the code in the Chrome console (in Sources) so it’s definitely loaded, but the DIVs and text fields are still displayed.
    Would this be an issue with a different portal version?
    I was hoping to be able to investigate this solution and add to it. Thanks!

    Like

    1. If you are still seeing the items it could have to do with a portal version difference, or how the task is loading. We’ve had some discrepancy in certain versions / environments where the code runs before the activities are fully populated so it doesn’t remove the fields. The code here below actually applies the changes when the mouse enters the activity area of the form, so it should be fully loaded at this point.


      //start hide activity fields
      app.custom.formTasks.add('ServiceRequest', null, function(formObj, viewModel){
      formObj.boundReady(function () {
      var targetFields = [
      "Area",
      "Priority",
      "Stage",
      "Scheduled Start",
      "Scheduled End",
      "Impacted Configuration Items"
      ]

      fn_HideActivityFields(targetFields);
      });
      });

      function fn_HideActivityFields (fields) {
      $("div.panel-heading:contains('Activities')").parent().on("mouseenter", function (){
      console.log("I'm hiding fields!", fields);
      for(var i=0; i < fields.length; i++){
      var label = fields[i];
      var item = $("div.activity-item-form").find("label span:contains(" + label + ")");
      $(item).each(function () {
      var ctrl = $(this).parents("div")[2];
      $(ctrl).hide();
      });
      }
      });
      }
      //END hide activity fields

      Like

  2. Seth–How would we show an activity field? For example, we have extended the Manual Activity to include Support Group. How can we show the support group field for MAs?

    Like

    1. In short, you have to follow a similar procedure as the above to find the work item activity by type that you want to work with. Then you have to dynamically add a control to that form and bind it to the proper place in the view model.

      It’s fairly complicated, much more so than just hiding them. I’ll add it to my list of blog posts over the next week or so. If you have something more urgent, we can get to it faster via a services engagement.

      Like

      1. Thanks Seth! Not having the Support Group field in the MA form on Service Requests has been a pain point for some of our analysts, but not overwhelming.

        Liked by 1 person

Leave a reply to Matt Howard Cancel reply