0

The scenario I have is to create dynamic table using javascript by passing the data passed from script tag. My javascript code parses the provided json and generates the table header and table body. The table body is generated along with the tags required for angular binding method {{variable_name}}.

But after the DOM is created I need to re-apply the scope to ng-repeat of table.

<html>
<head>
<title>dynamic table</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <script src="js/angular.min.js"></script>
    <script src="js/jquery.min.js"></script>

<script type="text/javascript">
var orderByField = "impressions";
var reverseSort = "false";
var myList = [{firstName: 'John',lastName: 'Doe',age: 30,etc : 'heelo'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Sue',lastName: 'Banter',age: 21,etc: 'cool'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'},{firstName: 'Frank',lastName: 'Burns',age: 54,etc: 'world'}];


function addAllColumnHeaders(myList, selector)
{   
    var columnSet = [];
    var headerTr$ = $('<tr/>');
    var aStart = '<a href="#" ng-click="orderByField=\'';
    var aMid = '\'; reverseSort = !reverseSort">';
    var aEnd = '</a>';

    for (var i = 0 ; i < myList.length ; i++) {
        var rowHash = myList[i];
        for (var key in rowHash) {
            keyLink = aStart+key+aMid+key+aEnd;
            if ($.inArray(key, columnSet) == -1){
                columnSet.push(key);
                headerTr$.append($('<th/>').html(keyLink));
            }
        }
    }
    $(selector).append(headerTr$);
    return columnSet;
}

function createAngularTableDataPlaceholder(myList, selector)
{
    var columnSet2 = [];
    var headerTr2$ = $('<tr/>').attr('ng-repeat','field in myList|orderBy:orderByField:reverseSort');
    var aStart2 = '<td>{{field.';

    var aEnd2 = '}}</td>';

    for (var i = 0 ; i < myList.length ; i++) {
        var rowHash2 = myList[i];
        for (var key2 in rowHash2) {
            keyLink2 = aStart2+key2+aEnd2;
            //alert(keyLink);
            if ($.inArray(key2, columnSet2) == -1){
                columnSet2.push(key2);
                headerTr2$.append($('<td/>').html(keyLink2));
            }
        }
    }
    $(selector).append(headerTr2$);
    return columnSet2;
}
</script>
</head>
<body>
<div class="container">
<section ng-app="app" ng-controller="MainCtrl" ng-init="getMember(myList)">
<table class="table" id="excelDataTable" border="1">
            <thead id="thead">

            </thead>
            <tbody id="tbody">
              <!--tr ng-repeat="field in myList|orderBy:orderByField:reverseSort">

              </tr-->
            </tbody>
  </table>
  </section>
  </div>

  <script>
    var app = angular.module('app', []);

        app.controller('MainCtrl', ['$scope', '$window', function($scope, $window) {        

                addAllColumnHeaders(myList, '#thead');
                createAngularTableDataPlaceholder(myList, '#tbody');
                console.log("header and columns done");

                $scope.orderByField = $window.orderByField;
                console.log($scope.orderByField);

                $scope.reverseSort = false;
                console.log($scope.reverseSort);

                angular.element(document).ready(function () {
                $scope.myList = $window.myList;
                console.log("got "+$scope.myList);
            });

        }]);    
    </script>

</body>
</html>

The dom elements created are as - enter image description here

The current output I am getting is as - enter image description here But the problem is that angular binds all its code at rendering time. How can I use the $scope.watch method or $scope.apply method to get this done after javascript is done. I was trying to do this using

angular.element(document).ready(function ())

but that's not the correct way I suppose.
I am new to angular. Please guide me. Thanks!

Hunter Turner
  • 6,804
  • 11
  • 41
  • 56
Dev Utkarsh
  • 1,377
  • 2
  • 18
  • 43
  • 1
    You shouldn't be creating the dom with jQuery in the first place. The data should be passed into a controller and let angular build the dom – charlietfl Jul 15 '16 at 19:45
  • 1
    I would put all of your js logic in the angular controller to start with – Justin Herter Jul 15 '16 at 19:45
  • 2
    Strongly suggest reading [thinking-in-angularjs-if-i-have-a-jquery-background](http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background) – charlietfl Jul 15 '16 at 19:47
  • Thank you @charlietfl and Justin. This seems more logical. I passed all my code to controller to build the dom. But still its the same error. As I think that ng-app is getting rendered before and components are created later maybe ? – Dev Utkarsh Jul 15 '16 at 20:32
  • The thread is really useful! Thanks again @charlietfl :) – Dev Utkarsh Jul 15 '16 at 20:36
  • does that mean you got rid of the jQuery and are using angular templating ? – charlietfl Jul 15 '16 at 20:36
  • @charlietfl I want to but am not sure if right now I will be able to generate dynamic templates from angular. I am exploring & studying though and also meanwhile trying to add the band-aid on this one. :p – Dev Utkarsh Jul 15 '16 at 20:49
  • 1
    you need an `ng-repeat` to populate that table. Most tutorials will show this. Go through tutorial on angular docs site step by step. Will save you a lot of problems later understanding the basics – charlietfl Jul 15 '16 at 21:05

1 Answers1

1

You can bootstrap angular after DOM tree is rendered. Just remove ng-app from section and put this code at the end of first script:

var elem = document.querySelector('section');
angular.bootstrap(elem, 'app');

Of course, use better way to select your element on which you want to bind ng-app to

  • All this will do is throw a band-aid on a poorly set up app – charlietfl Jul 15 '16 at 19:53
  • Thanks @bohdan, this is how I can patch the code i believe. I added an id to the section for proper selection of section tag and am trying to use the bootstrapping, but with no success. Where exactly should I put this ? – Dev Utkarsh Jul 15 '16 at 20:34
  • @devutkarsh , at the end of first code. But probably now your angular module code should go first. So first script tag angular.module('app')... second script - your dom rendering. But also it'll be better to use console. Often angular throws understandable mistakes and you should read it – Bohdan Huseinov Jul 15 '16 at 21:42
  • but don't forget to remove ng-app='app' from section, let angular.bootstrap do that stuff – Bohdan Huseinov Jul 15 '16 at 21:44