Search code examples
javascripthtmlasp.netdata-bindingdotvvm

Value binding in <script>-tag not working


Is there a way how to use value binding in <script>-tags using DotVVM? I want to display the properties of the ViewModel as text. Here i want to set the labels and data of a chart using chartjs.

That's what i got so far:

I'm trying to get a chart using chartjs working. ViewModel: (The variables are getting filled with data in PreRender() Method)

private List<int> chartLabels = new List<int>();
private List<int> chartData1 = new List<int>();

public string ChartLabels
{
    get { return JsonConvert.SerializeObject(chartLabels); }
}

public string ChartData1
{
    get { return JsonConvert.SerializeObject(chartData1); }
}

The dothtml file:

<canvas id="myChart" style="padding: 0;margin: auto;display: block; "> </canvas>

<script>   
    var dataT = {
        labels: {{value: ChartLabels}},
            datasets: [{
                label: "Africa",
                data: {{value: ChartData1}},
                fill: false,
                backgroundColor: "rgba(255, 0, 0, 0.8)",
                borderColor: "rgba(255, 0, 0, 0.8)",
                borderWidth: 1
            }]
        };

        var ctx = $("#myChart").get(0).getContext("2d");
        var myNewChart = new Chart(ctx, {
            type: 'line',
            data: dataT,
            options: {
                responsive: true,
                title: { display: true, text: 'World population per region (in millions)' },
                legend: { position: 'bottom' },
                scales: {
                    xAxes: [{ gridLines: { display: false }, display: true, scaleLabel: { display: false, labelString: '' } }],
                    yAxes: [{ gridLines: { display: false }, display: true, scaleLabel: { display: false, labelString: '' }, ticks: { stepSize: 250, beginAtZero: true } }]
                },
            }
        });  
</script>

Putting all together this is what i get when i open the page:

<script>

    var dataT = {
        labels: <!-- ko text: ChartLabels --><!-- /ko -->,
            datasets: [{
                label: "Africa",
                data: <!-- ko text: ChartData1 --><!-- /ko -->,
                fill: false,
                backgroundColor: "rgba(255, 0, 0, 0.8)",
                borderColor: "rgba(255, 0, 0, 0.8)",
                borderWidth: 1
            }]
        };

        var ctx = $("#myChart").get(0).getContext("2d");
        var myNewChart = new Chart(ctx, {
            type: 'line',
            data: dataT,
            options: {
                responsive: true,
                title: { display: true, text: 'World population per region (in millions)' },
                legend: { position: 'bottom' },
                scales: {
                    xAxes: [{ gridLines: { display: false }, display: true, scaleLabel: { display: false, labelString: '' } }],
                    yAxes: [{ gridLines: { display: false }, display: true, scaleLabel: { display: false, labelString: '' }, ticks: { stepSize: 250, beginAtZero: true } }]
                },
            }
        });

    </script>

At line <!-- ko text: ChartLabels --><!-- /ko -->, im getting this error

Uncaught SyntaxError: Unexpected token :

Does somebody know how to use proper value binding (here: displaying it as text in a <script>-tag)?


Solution

  • Value bindings don't work in script elements - they are translated to Knockout JS expressions (the HTML comments you have in the code snippet).

    You have two options:

    1. Use resource binding: {{resource: ChartLabels}} You need to do all the conversions so it will produce a valid JavaScript expression - it just renders a string in the output HTML.

    2. You may use JavaScript to get the values directly from the viewmodel:

    var vm = dotvvm.viewModels.root.viewModel;
    
    // you need to use () to read the value of Knockout observables 
    var chartLabels = vm.ChartLabels();   
    

    The viewmodel on the client side is wrapped in Knockout observables, so make sure you don't forget () to access the value.