I wish to pass data from a Grails controller to a chart.js chart in a Grails view. My code will not display the chart labels correctly. The issue is that labels
(an arrayList of dates) is not being read correctly as an array of strings in Javascript which is causing Chart.js not to display.
Can anyone offer any help?
Any help would be gratefully received. Thanks in advance! My code is here:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script> <script> var userResult = ${userResultMap as JSON}; var data = userResult.result; var labels = userResult.dateCreated; var config = { type: 'line', data: { labels: testDate, datasets: [{ label: 'Clinical FRE', backgroundColor: '#7A564A', borderColor: '#7A564A', data: result, fill: false }] }, options: { legend: { display: false }, tooltips: { enabled: false }, responsive: true, scales: { yAxes: [{ gridLines: { drawBorder: false, color: ['#9b1f22', '#9b1f22', '#ed1c24', '#ed1c24', '#f7931f', '#f7931f', '#206b36', '#206b36', '#206b36', '#206b36', '#206b36'] }, ticks: { min: 0, max: 100, stepSize: 10, callback: function (value) { return value + "%" } } }] } } }; window.onload = function createChart(data) { var ctx = document.getElementById('myChart').getContext('2d'); window.myLine = new Chart(ctx, config) }; </script>
Data is sent from controller using ModelandView command:
@Secured('ROLE_USER') def home() { try { SecUser user = springSecurityService.currentUser Participant p = Participant.findByUser(user) Result userResults = Result.findByUser(user) def userResultsList def riskLevelMap def iconClassMapList = [] def riskLevelMapList = [] def colourNameList = [] Map userResultMap = [:] if (userResults!= null){ userResultsList = userResults.list() if(userResultsList != null) userResultsList.each {list-> iconClassMapList.add(previousTestsService?.getIconType(list)) riskLevelMap = riskAdviceService?.riskLevel(list.result) riskLevelMapList.add(riskLevelMapList) colourNameList.add(riskLevelMap?.colourName) } userResultMap.put("result",userResultsList?.result) userResultMap.put("dateCreated",userResultsList?.dateCreated) println userResultMap println userResultsList.dateCreated println(userResultsList.dateCreated.getClass()) } return new ModelAndView('home', [user: user, participant: p, username: user.username,userResultsList: userResultsList,iconClassMapList:iconClassMapList,colourNameList:colourNameList,userResultMap:userResultMap]) } catch (Exception ex) { log.error(ex.printStackTrace()) } }
Sample data: data
- [13.7] labels
- [2018-09-17 16:39:00.0]
4 Answers
Answers 1
You would need to convert your array, object whatever you are using to JSON for JavaScript to understand it.
<g:javascript> var testDate = ${userResultsList.dateCreated} var result = ${userResultsList.result as JSON} // make sure grails.converters.JSON is imported </g:javascript>
Answers 2
Make sure userResultsList(userListMap) data must be in the form below from the controller.
Map userResultMap = [:] List dateCreated = ["2018-09-17 13:07:06.0","2018-09-17 13:27:06.0","2018-09-17 14:27:06.0","2018-09-17 17:27:06.0"] List result = [50, 56, 23, 42] userResultMap.put("dateCreated",dateCreated) userResultMap.put("result",result)
Then you need to parse the userResultMap data as JSON if not parsed and do similar like this in gsp page:
<script> var userResult = ${userResultMap as JSON}; var result = userResult.result; var labels = userResult.dateCreated; </script>
Answers 3
The main issue here is that grails automatically escapes values as HTML upon insertion in the GSP page. You can suppress this by adding the advice
<%@ expressionCodec="none" %>
at the beginning of the GSP page.
Be aware that your application will be less secure after the change. Especially if the data can contain user-created input people might start messing with your application.
Here is a running example using Grails 3.3.8 based on the test data supplied by @Kumar Chapagain, thank you very much.
In the controller you don't need to package the data in a ModelAndView, as this is done automatically by Grails. Just return a map with the needed entries. I prefer to convert the map to JSON within the controller and not in the gsp page as it keeps the control where it belongs and the GSP more simple.
Controller:
package g338 import grails.converters.JSON class ChartController { def index() { Map userResultMap = [:] List dateCreated = ["2018-09-17 13:07:06.0","2018-09-17 13:27:06.0","2018-09-17 14:27:06.0","2018-09-17 17:27:06.0"] List result = [50, 56, 23, 42] userResultMap.put("dateCreated",dateCreated) userResultMap.put("result",result) [ userResultMap: userResultMap as JSON ] } }
gsp page: views/chart/index.gsp
<%@ expressionCodec="none" %> <!doctype html> <html> <head> <meta name="layout" content="main"/> <title>Welcome to Grails</title> </head> <body> <canvas id="myChart"></canvas> <g:javascript> var result = ${userResultMap}; var data = result.result; var labels = result.dateCreated; var config = { type: 'line', data: { labels: labels, datasets: [{ label: 'Clinical FRE', backgroundColor: '#7A564A', borderColor: '#7A564A', data: result, fill: false }] }, options: { legend: { display: false }, tooltips: { enabled: false }, responsive: true, scales: { yAxes: [{ gridLines: { drawBorder: false, color: ['#9b1f22', '#9b1f22', '#ed1c24', '#ed1c24', '#f7931f', '#f7931f', '#206b36', '#206b36', '#206b36', '#206b36', '#206b36'] }, ticks: { min: 0, max: 100, stepSize: 10, callback: function (value) { return value + "%" } } }] } } }; window.onload = function createChart(data) { var ctx = document.getElementById('myChart').getContext('2d'); window.myLine = new Chart(ctx, config) }; </g:javascript> </body> </html>
Answers 4
var labels = userResult.dateCreated; var config = { type: 'line', data: { labels: testDate,
you are using labels: testDate, but assigning labels to labels try
var testDate = userResult.dateCreated; **labels: testDate**
0 comments:
Post a Comment