0

I am dynamically building a table based on what SQL returns me. In the example below, I can fill a table with the start time, end time and user with no issue:

var StartTime = document.createElement('td');
var EndTime = document.createElement('td');
var InUser = document.createElement('td');
StartTime.innerText = value[i].startTime;
EndTime.innerText = value[i].endTime;
InUser.innerText = value[i].inUser;

The output will be a table with the number of entries I have received from SQL. What I would like to do now is create another td element to add to the last column of the table. This will be a button that will allow me to show and hide certain rows. For some reason, the ng-click functionality does not work when I click the button. Below is how I create the td element and how I apply the button to it.

var ViewComments = document.createElement('td');
ViewComments.innerHTML = '<button type="button" ng-click="showHideComments()" class="r-primary-button">View Comments</button>';//apply click functionality.

When Ctrl + Shift + C clicking on the table to view the elements on the page, I can see that the row has the exact values that I specified (i.e. the type, ng-click and class). The class property is working because I have the background of the button set to blue when highlighted which gives the "clicking effect." I am not sure why the ng-click functionality is not working because I have used ng-click before in the application where buttons are not dynamically created. I'm assuming this the issue? If so, is there a way to get the ng-click functionality to work on dynamically create buttons?

I see in this stackoverflow that they are using $compile: ng-click not working from dynamically generated HTML
Is this the only way to solve this problem?

Any help would be appreciated!

  • 1
    Yes, you must use $compile. – Rani Radcliff Jun 27 '17 at 17:37
  • Where to start with this one... why aren't you using `ng-repeat` to create your table? You don't need `$compile` if you do it "the Angular way". Read this before doing anything else: https://stackoverflow.com/q/14994391/64279 – adam0101 Jun 27 '17 at 17:40
  • I've seen ng-repeat before, but how do take advantage of that once SQL returns its values? The SQL table only gets returned when the user clicks on the "view comments" button. Do I set the data that gets returned like so? $scope.returnValues = commentsReturned? And then ng-repeat in the DOM will run and fill the table? I've only been using JavaScript for a few weeks so I'm still fairly new to this. Thanks again. – SQL and Java Learner Jun 27 '17 at 17:58
  • @SQLandJavaLearner, yes, you've got it. Or if you are using paging, you'd concatenate the new records returned by the server to your existing results array. If you're building a table, you'll probably also want to learn about `ng-repeat-start` and `ng-repeat-end` - depending on the complexity of the table you are making. – adam0101 Jun 27 '17 at 18:00
  • @SQLandJavaLearner yes something like that, see my answer below – Bunyamin Coskuner Jun 27 '17 at 18:01
  • @SQLandJavaLearner, Don't listen to the people telling you to use `$compile`. That's for more complex scenarios. You don't need it for what you're trying to do. Go with @BunyaminCoskuner's answer. – adam0101 Jun 27 '17 at 18:03
  • Thank you all, that worked! However, I am running into an issue with ng-repeat-start and ng-repeat-end. I have asked the question here https://stackoverflow.com/questions/44788149/create-new-rows-for-nested-objects in case anyone would like to lend a hand! – SQL and Java Learner Jun 27 '17 at 19:16
  • @SQLandJavaLearner, remember to click the check mark next to the answer that best answered your question. – adam0101 Jun 28 '17 at 13:44

2 Answers2

2

Why aren't you using angular utilities? This seems like a lot of work while it can be easily done with angular.

<table ng-if="values">
    <tr ng-repeat="value in values">
        <td>{{value.startTime}}</td>
        <td>{{value.endTime}}</td>
        <td>{{value.inUser}}</td>
        <td><button type="button" ng-click="showHideComments()" class="r-primary-button">View Comments</button></td>
    </tr>
</table>

Inside your controller

$http.get(someUrl).then(function(data){
    $scope.values = data;
});


$scope.showHideComments = function() {
    // do your thing here
};
Bunyamin Coskuner
  • 8,719
  • 1
  • 28
  • 48
0

Yes go with compile.

As the doc says that

Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together.

You can create a reusable directive which will take the dynamic string and compiles that.

An example

<div ng-controller="Controller">
  <element-create message='htmlString'></element-create>
</div>

Directive

angular.module("CompileDirective", [])
  .directive('elementCreate', ['$compile', function ($compile) {
      return { 
        restrict: 'E', 
        scope: {
            message: "="
        },
        replace: true,
        link: function(scope, element, attrs) {
            var template = $compile(scope.message)(scope);
            element.replaceWith(template);               
        },
        controller: ['$scope', function($scope) {
           ...
        }]
      }
  }])
Navoneel Talukdar
  • 4,393
  • 5
  • 21
  • 42