Adding a line to a chart using the advanced area


#1

Hi, I’ve got a list that contains data on when someone was admitted to hospital and the ward they were admitted to. I’m using columns called MonthAdmitted (which has the month they were admitted e.g. 6) and Ward.

In the aggregation section I’ve grouped by Ward and set up tmpMonthTotal which is a count of MonthAdmitted.

I’ve then added some code to the Dashboard Advanced section:
var handlers = {};
handlers.preRender = function (config, logger) {
logger.debug('Configuration: ', config);

var data = config.series[0].data;

config.series.push({
    name: 'Total',
    type: 'line',
    data: data,
    field: 'tmpMonthTotal',
    categoryField: 'MonthAdmitted',
    tooltip: {
    visible: true
  }
});

window.config = config;
return true;

}

The bar chart looks fine, but I can’t get the line that I’ve added, which I want to display the total admissions for the month, to show up properly on the chart. Please tell me what I’m doing wrong.

“Display each group as a separate series” is ticked, which I think may be an issue, but without it my bar chart doesn’t display properly.

Thank you.



#2

Hello, Alice!
This was quite a complex case, but not impossible. The main difficulty arose from the multiple series used in this graph, while most our examples only used one. But this can be overcome using JavaScript in Dashboard -> Advanced settings:


Here is my code, hope it will work for you, might need slight adjustments first:

var handlers = {};
handlers.preRender = function (config, logger) {
  	 var myData = [];
  	 var map = new Map;

     data.items.forEach(function (el) {
       map.set(el.Month, (map.get(el.Month) ? map.get(el.Month) : 0) + 1);
     });
  
  	 let keys = Array.from( map.keys() );

  	for (var i = 0; i < keys.length; i++){
          var obj = {};
          obj.Month = keys[i];
          obj.value = map.get(keys[i]);
          myData.push(obj);
  	}
 
    config.series.push({
        type: 'line',
      	data: myData,
      	categoryField: 'Month',
      	field: 'value',
        name: "Total",
      	tooltip: {
	    visible: true
	}
    });
 
    logger.debug('Configuration: ', config);
    window.config = config;
  
    return true;
}

#3

Thank you for replying Nikita. I’m getting an error
09:29:31 ERROR - Pre-rendering failed: TypeError: Object doesn’t support property or method ‘keys’

when I process - is there something I need to include? Sorry - my javascript skills are limited.


#4

Hello, Alice!
Most likely you are using IE or Edge, maybe an older version of another browser, and they might not support keys - developer.mozilla.org/en-US/doc … bject/keys

Try adding this code before yours, it might solve the issue:

// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
  Object.keys = (function() {
    'use strict';
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
        dontEnums = [
          'toString',
          'toLocaleString',
          'valueOf',
          'hasOwnProperty',
          'isPrototypeOf',
          'propertyIsEnumerable',
          'constructor'
        ],
        dontEnumsLength = dontEnums.length;

    return function(obj) {
      if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === null)) {
        throw new TypeError('Object.keys called on non-object');
      }

      var result = [], prop, i;

      for (prop in obj) {
        if (hasOwnProperty.call(obj, prop)) {
          result.push(prop);
        }
      }

      if (hasDontEnumBug) {
        for (i = 0; i < dontEnumsLength; i++) {
          if (hasOwnProperty.call(obj, dontEnums[i])) {
            result.push(dontEnums[i]);
          }
        }
      }
      return result;
    };
  }());
}

#5

Well, some very strange results - the original code and the new code work in Chrome when I do a preview. However, when I save my work and look at the page it doesn’t display the chart at all! Instead it says “An Error has occured during rendering. Please, get more detail in the browser console.”. I go back into Plumsail, don’t change anything, do a preview and it still works. Very odd.

In IE I still get the same error as before (the one about ‘keys’) when I try to do a preview, even with the new code. The page displays the bar chart but not the line.


#6

Hello, Alice!
Regarding the problem in Google Chrome - it’s my bad.
What you need to do to make it work is to split code in two parts, one part goes to Data Source and another goes to Dashboard. Here are the screenshots and the code:


handlers.aggregationSuccess = function(data, logger) {
  window.myData = [];
  var map = new Map;

  data.items.forEach(function (el) {
    map.set(el.Month, (map.get(el.Month) ? map.get(el.Month) : 0) + 1);
  });
  
  let keys = Array.from( map.keys() );
  
  for (var i = 0; i < keys.length; i++){
    var obj = {};
    obj.Month = keys[i];
    obj.value = map.get(keys[i]);
      
    myData.push(obj);
  }
  
  return true;
}


var handlers = {};
handlers.preRender = function (config, logger) {
    config.series.push({
        type: 'line',
      	data: myData,
      	categoryField: 'Month',
      	field: 'value',
      	name: "Total",
      	tooltip: {
	  visible: true
	}
    });
 
    logger.debug('Configuration: ', config);
  window.config = config;
  
    return true;
}

P.S. If you need support for Internet Explorer, we can most likely write code for you and post it here tomorrow. For now, this code should work in Google Chrome and other browsers that support keys object.


#7

Thanks Nikita - that does now work in Chrome. Hooray! But … yes I do need it to work in IE. Sorry - please can you help?


#8

Hello, Alice!
Try this code in Data Source -> Advanced:

handlers.aggregationSuccess = function(data, logger) {
  window.myData = [];
  var monthObj = {};

  data.items.forEach(function (el) {
    if(monthObj[el.Month]){
        monthObj[el.Month] += 1;
    }
    else{
    	monthObj[el.Month] = 1;
    }
  });
  
  
  for (var property in monthObj) {
    if (monthObj.hasOwnProperty(property)) {
      var obj = {};
      obj.Month = property;
      obj.value = monthObj[property];
      myData.push(obj);
    }
}
  
  return true;
}

#9

Hi Nikita, I’m afraid it’s still not working. Can I please just check I’ve done the right thing? The field I’m using is called MonthAdmitted. In Datasource Advanced I’ve got this:

[code]handlers.aggregationSuccess = function(data, logger) {
window.myData = [];
var monthObj = {};

data.items.forEach(function (el) {
if(monthObj[el.MonthAdmitted]){
monthObj[el.MonthAdmitted] += 1;
}
else{
monthObj[el.MonthAdmitted] = 1;
}
});

for (var property in monthObj) {
if (monthObj.hasOwnProperty(property)) {
var obj = {};
obj.Month = property;
obj.value = monthObj[property];
myData.push(obj);
}
}

return true;
}

handlers.aggregationError = function(error, logger) {
return $.Deferred().reject(error);
}

handlers.finish = function(data, logger) {
logger.debug('Data is processed: ', data);
return true;
}[/code]

And in Dashboard Advanced I have this:

[code]var handlers = {};
handlers.preRender = function (config, logger) {

config.series.push({
    type: 'line',
     data: myData,
     categoryField: 'MonthAdmitted', //or Month?
     field: 'value',
     //name: "Total",
     tooltip: {
   visible: true

}
});

logger.debug('Configuration: ', config);
window.config = config;

return true;

}
[/code]


#10

It should work, just tested it once again. Don’t worry about Dashboard -> Advanced settings, they are the same for IE and Chrome, so if it works for Chrome then the problem is in Data Source -> Advanced tab.

Most likely the issue is that you didn’t change
obj.Month = property;
to
obj.MonthAdmitted = property;

Try this and tell me if it works or not.


#11

Hi, I’m afraid that still doesn’t work - I get this error when doing a preview:
11:20:54 ERROR - Pre-rendering failed: ReferenceError: myData is not defined


#12

You can try to replace myData with window.myData,though I am not sure this will help as it should work either way.

Try to open browser’s console, it’s F12 in IE and see if there are any errors when you try to build the chart.


#13

That does get rid of the error, but the line still won’t appear on the chart. Nothing in the browser console either. I’m convinced it must be something simple, but I just don’t know what it can be.


#14

Make extra sure that all Month titles are replace with MonthAdmitted, but as I see, you did that in almost all cases, if not all by now. Also, try to upgrade Internet Explorer, maybe you have an older version.

I will also try to write code with additional logger commands to test how well does this code run on your part. It works for me, but maybe we have some differences in our lists, for example.


#15

Here is the code I want you to include in your Data Source -> Advanced tab:

var handlers = {};

handlers.init = function(data, logger) {
  data.items = [
    {value: 0, finger: 'Thumb', red: 0, green: 100},
    {value: 100, finger: 'Index', red: 160, green: 100},
    {value: 160, finger: 'Middle', red: 80, green: 100},
    {value: 100, finger: 'Ring', red: 60, green: 100},
    {value: 80, finger: 'Pinky', red: 40, green: 100}
  ];
  logger.debug('Data is initialized: ', data);
  return true;
}

handlers.requestInit = function(query, logger) {
  return true;
}

handlers.requestSuccess = function(data, logger) { 
  return true;
}

handlers.requestError = function(error, logger) {
  return $.Deferred().reject(error);
}

handlers.aggregationSuccess = function(data, logger) {
  window.myData = [];
  var monthObj = {};

  data.items.forEach(function (el) {
    if(monthObj[el.MonthAdmitted ]){
        monthObj[el.MonthAdmitted ] += 1;
    }
    else{
       monthObj[el.MonthAdmitted ] = 1;
    }
  });
 
 
  for (var property in monthObj) {
    if (monthObj.hasOwnProperty(property)) {
      var obj = {};
      obj.MonthAdmitted = property;
      obj.value = monthObj[property];
      window.myData.push(obj);
    }
  for(var i = 0; i < window.myData.length; i++){
    logger.debug("Month admitted: " + window.myData[i].MonthAdmitted + " .Amount: " + window.myData[i].value);
  }
}
 
  return true;
}

handlers.aggregationError = function(error, logger) {
  return $.Deferred().reject(error);
}

handlers.finish = function(data, logger) {
  logger.debug('Data is processed: ', data);
  return true;
}

It should produce result similar to this in the logger console:


Next, include this code in Dashboard -> Advanced tab:

var handlers = {};
handlers.preRender = function (config, logger) {
    for(var i = 0; i < window.myData.length; i++){
      logger.debug("Month admitted: " + window.myData[i].MonthAdmitted + " .Amount: " + window.myData[i].value);
    }
  
    config.series.push({
        type: 'line',
         data: window.myData,
         categoryField: 'MonthAdmitted',
         field: 'value',
         tooltip: {
       visible: true
   }
    });
 
    logger.debug('Configuration: ', config);
    window.config = config;
 
    return true;
}

Then switch from Preview to Console on the bottom of the Dashboard Designer and it should have result similar to this:



#16

Hi Nikita, thank you for all your help with this. I’m afraid I still have no line on my chart. I’ve followed your instructions, here are the results.

Data Source screen shot:


and data export:

{"items":[{"ID":44,"MonthAdmitted":4,"Ward":"Aspen","YearAdmitted":2017},{"ID":46,"MonthAdmitted":4,"Ward":"Cedar","YearAdmitted":2017},{"ID":47,"MonthAdmitted":4,"Ward":"Birch","YearAdmitted":2017},{"ID":45,"MonthAdmitted":5,"Ward":"Falcon","YearAdmitted":2017},{"ID":41,"MonthAdmitted":6,"Ward":"Falcon","YearAdmitted":2017},{"ID":42,"MonthAdmitted":6,"Ward":"Swan","YearAdmitted":2017},{"ID":43,"MonthAdmitted":6,"Ward":"Swan","YearAdmitted":2017}],"groups":[{"field":"Ward","value":"Aspen","items":[{"ID":44,"MonthAdmitted":4,"Ward":"Aspen","YearAdmitted":2017}],"hasSubgroups":false,"aggregates":{"MonthAdmitted":{"count":1}},"tmpMonthTotal":1},{"field":"Ward","value":"Birch","items":[{"ID":47,"MonthAdmitted":4,"Ward":"Birch","YearAdmitted":2017}],"hasSubgroups":false,"aggregates":{"MonthAdmitted":{"count":1}},"tmpMonthTotal":1},{"field":"Ward","value":"Cedar","items":[{"ID":46,"MonthAdmitted":4,"Ward":"Cedar","YearAdmitted":2017}],"hasSubgroups":false,"aggregates":{"MonthAdmitted":{"count":1}},"tmpMonthTotal":1},{"field":"Ward","value":"Falcon","items":[{"ID":45,"MonthAdmitted":5,"Ward":"Falcon","YearAdmitted":2017},{"ID":41,"MonthAdmitted":6,"Ward":"Falcon","YearAdmitted":2017}],"hasSubgroups":false,"aggregates":{"MonthAdmitted":{"count":2}},"tmpMonthTotal":2},{"field":"Ward","value":"Swan","items":[{"ID":42,"MonthAdmitted":6,"Ward":"Swan","YearAdmitted":2017},{"ID":43,"MonthAdmitted":6,"Ward":"Swan","YearAdmitted":2017}],"hasSubgroups":false,"aggregates":{"MonthAdmitted":{"count":2}},"tmpMonthTotal":2}]}

Dashboard advanced screen shot:


I’m using Internet Explorer 11 (which I don’t have a choice about at work). Maybe it’s just not capable of doing this.


#17

Hello, Alice!
That shouldn’t be an issue as I’ve tested it in IE11 myself. What might cause the issue, is if you are using SharePoint classic design pages, it automatically switches to functionality of IE10, but that shouldn’t be an issue on modern design pages.

Thank you for the Data export, can you also send us your chart configuration? That way we will test your Data with your configuration and will hopefully get a solution ready for you!


#18

Hello,

I’ve emailed the list template with data to [email protected] - if you need anything else please let me know. I wasn’t sure if you wanted screenshots of all the chart settings.

Alice.