asgaines
asgaines

Reputation: 307

AngularJS ng-repeat: Dynamically render/bind canvas inside loop

Relatively new to the world of AngularJS, enjoying it so far.
However, I'm struggling with my attempt to loop through entries in my db and render a <canvas> for each one.

Say this is my data (shortened for brevity):

var paintings = [
    { "_id" : ObjectId("31c75"), "data" : "0,0,0,0" },
    { "_id" : ObjectId("deadb"), "data" : "1,3,0,255" }
];

Which is loaded into the controller by a factory:

app.factory('paintings', ['$http', function($http) {
    var o = {
        paintings: []
    };
    o.getAll = function() {
        return $http.get('/paintings')
            .success(function(data) {
                angular.copy(data, o.paintings);
            });
    }
    return o;
}]);

I'm wanting to loop through each entry and construct a <canvas> element, then pass that <canvas> element to another object (Grid) with data as an argument, which creates context and draws on that <canvas> based on the data.

Simple, right? Unfortunately, I'm at a loss for how to do so and do not have the language with which to ask a more poignant question.
I think problems exist in the fact that I am using inline-templates which aren't yet rendered.

This is generally the approach I am currently trying:

HTML:

<div ng-repeat="painting in paintings" some-directive-maybe="bindCanvas(painting._id)">
    <canvas id="{{ painting._id }}" width="800" height="400"></canvas>
</div>

JS:

app.controller('PaintingCtrl', [
    '$scope',
    function($scope) {
        $scope.bindCanvas(canvasId) {
            var grid = new Grid(document.getElementById(canvasId));
            // Have fun with grid
        }
    }
]);

Help me, StackOverflow. You're my only hope...

Upvotes: 3

Views: 1820

Answers (2)

rohit kumbhar
rohit kumbhar

Reputation: 121

Following code also works for repeat chart on the same page.

<div ng-repeat="a in abc">
    <canvas id="pieChart{{a}}" ng-bind = "bindCanvas(a)" ></canvas>
<div>

Add below code in JS file

$scope.abc = [1,2,3];

$scope.bindCanvas = function(i) {
    var ctx = document.getElementById("pieChart"+i);
    new Chart(ctx,{
        type: 'pie',
        data: {
            labels: ["Tele-conference", "Projector", "Laptop", "Desktop", "Coffee-machine"],
            datasets: [{
                label: "Population (millions)",
                backgroundColor: ["red", "green","blue","violet","yellow"],
                data: [200,100,300,400,150]
            }]
        },
    });
} 

Upvotes: 0

Ravi Teja
Ravi Teja

Reputation: 1107

var paintings = [
    { "_id" : ObjectId("31c75"), "data" : "0,0,0,0" },
    { "_id" : ObjectId("deadb"), "data" : "1,3,0,255" }
]; 

paintings should be in an array.

 app.controller('PaintingCtrl', [
        '$scope',
        function($scope) {
            $scope.bindCanvas(canvasId) {
                var grid = new Grid(document.getElementById(canvasId));
                // Have fun with grid
            }
            //paintings should be on scope for ng-repeat to find it.
            // If ng-repeat does not find paintings on scope then it will create a new empty paintings object on scope
            $scope.paintings = [ 
              { _id : "31c75", data : "0,0,0,0" },
              { _id : "deadb", data : "1,3,0,255" }
             ];

        }
    ]);

Update:

I have created 2 plunkers.

First, plunker just creates canvas elements with static width and height. Number of canvas elements created is based upon number of paintings in painting.json file.

Second, plunker goes a step further and creates canvas elements with dynamic width and height. Number of canvas elements created is based upon number of paintings in painting.json file. Here width and height are based upon data property in paintings.json file.

Hope this helps.

Upvotes: 3

Related Questions