0

Is there any way that I can create a template in AngularJS but not run it until some event?

Actually I am using SignalR. So when server calls a client function then I want some HTML to show based on the data sent by server.

Suppose I am making a Chess Game. I don´t have the board to display on the page until the server sends it. In HandleBar I can create a template and when the server sends the board in json format I can compile the template and display it on page.

 gameHub.client.buildBoard = function(game){
        var template = Handlebars.compile($("board-template").html());
        $("board").html(template(game.Board))
    }

This builBoard function gets called by server.

In AngularJS I have to create a Controller, but the $scope.board has not loaded let.

The angular Code is

<div ng-app="game">
<div ng-controller="boardController">
    <div ng-repeat="row in board.Pieces">
        // Display Pieces
    </div>
</div>

JS

var app = angular.module("game", []);
app.controller("boardController", function ($scope) {
    $scope.size = 5;
    $scope.board= [];
});

Here the board is initialized to empty array. Now the server will call the buildBoard() function with the necessary data required.

gameHub.client.buildBoard = function(board){
   // Code to take this board object and assign it to the $scope.board
}

From here (outside the scope of controller ), how can I update the $scope.board array?

Ivan
  • 19,560
  • 31
  • 97
  • 141
Harry
  • 1,572
  • 2
  • 17
  • 31
  • why down vote? I have already searched google and Stackoverflow. This [Quesiton](http://stackoverflow.com/questions/13561447/angularjs-and-handlebars-both-required-or-not) does not answer the question. – Harry Aug 14 '15 at 14:31
  • 2
    You were probably downvoted because your question is a bit unclear. I would update your question and delete this comment. – Rorschach120 Aug 14 '15 at 14:38

2 Answers2

1

While I believe you should explain yourself a bit more, and show some angular code, I think you are looking for a solution to a problem that angular doesn't have.

Consider this code:

<div class="board-thing" ng-bind-html="board" ng-hide="board === null"></div>



...
.controller('myController', function($scope) {
  $scope.board = null;

  gameHub.client.buildBoard = function(game) {
    $scope.board = game.board;
  });
})

When the data is loaded $scope.board is assigned to the data and the view is immediately updated through the scope and ng-bind-html. No need for any compilation!

Rorschach120
  • 1,200
  • 1
  • 11
  • 18
  • +1. The whole purpose of using angular is having the view update itself when the scope is changed. Mixing Angular and Handlebars is just wrong – Eloims Aug 14 '15 at 14:33
  • Actually client does not decide when it will happen. In signalR the client side function has to be in the form I explained in the question. i.e. $.connection.gameHub.client.foo = fucntion(data){}. From this function only I have to trigger the angularJS controller – Harry Aug 14 '15 at 14:35
  • Please update your question with more info pertaining to how the data is handled on the front-end. With some angular code. – Rorschach120 Aug 14 '15 at 14:35
  • @Eloims I am not mixing them. I am asking can one perform the functionality of other? – Harry Aug 14 '15 at 14:36
  • @Harry sorry for the misunderstanding – Eloims Aug 14 '15 at 15:03
  • Hmm, @Eloims is right, you shouldn't be trying to access scope from outside the controller. You could have your buildBoard function emit an event with the board attached to it. Listen for that in the controller and then assign it to scope. Basically what he said to do in his comment. – Rorschach120 Aug 14 '15 at 15:43
0

You can define directives to avoid cluttering your controller with presentation related code.

For all business related code, define services outside of your controller.

In this case, as you want push data, you need to define an event dispatcher ("Server") that will inform the controller when remote changes take place.

Here is an example controller and related template.

angular
    .module('app')

    .controller("ChessController", function($scope, Server) {
        $scope.list = [0, 1, 2, 3, 4, 5, 6, 7];
        $scope.pieces = [];

        // "Server" is an angular service that abstracts your connection with your server
        // which can be based on socket.io, a raw websocket, HTTP polling...
        var chessGame = Server.getChessGame('xxx');

        chessGame.on('init', function(pieces) {
            // pieces == [
            //  {x: 0, y: 0, type: "pawn", color: "white"}
            //  {x: 0, y: 3, type: "king", color: "white"}
            //  {x: 2, y: 0, type: "queen", color: "white"}
            // ];

            $scope.pieces = pieces;
        });

        chessGame.on('remote_piece_moved', function(move) {
            // remove pieces at destination
            $scope.pieces = $scope.pieces.filter(function(p) { return p.x != move.dest_x && return p.y != move.dest_y; })
            // move piece.
            var piece = $scope.pieces.find(function(p) { return p.x == move.start_x && p.y == move.start_y; });
            piece.x = move.dest_x;
            piece.y = move.dest_y;
        });
    });


    .directive('chessPiece', function() {
        return {
            scope: false,
            link: function(scope, element) {
                scope.$watch('pieces', function(pieces) {
                    var piece = pieces.find(function(p) { return p.x == scope.col && p.y == scope.row; });

                    if (piece)
                        element.html('<img src="pieces/' + piece.type + '-' + piece.color + '.jpg"/>')
                    else
                        element.html('');
                }, true);
            }
        }
    });

Template

<table ng-controller="ChessController">
    <tr ng-repeat="row in list">
        <td ng-repeat="col in list" chess-piece></td>
    </tr>
</table>
Eloims
  • 5,106
  • 4
  • 25
  • 41
  • Thanks for the clutter free code but please have a look at the last part of my question (I have updated it). I dont understand how from there I can access my controller's variables? – Harry Aug 14 '15 at 15:13
  • You can't and should not access your controller from a service. Define an event dispatcher that feeds from SignalR in a service, and subscribe to it from the controller. (You may need to use $scope.apply to help angular know when to refresh the view) – Eloims Aug 14 '15 at 15:39
  • Show us some of your signalr code if you need some help, but it is most likely already answered in other questions. Do you use this https://github.com/JustMaier/angular-signalr-hub ? – Eloims Aug 14 '15 at 15:45