2

I have pretty simple Angular app that includes a factory and a controller. The factory is successfully supplying the data and the controller is successfully calling the data and taking action on it. The problem occurs when i try to append the data into the view. Using the code below, I get the following error:

"Error: Argument 1 of Node.appendChild is not an object."

app.js

var myModule = angular.module('myModule', []);

        myModule.factory('loanRepository', function(){
            return {
                getAllloans: function() {
                    return [
                        { LoanID: '1', LoanName: '101 Sample', LoanAmount: '1000000'},
                        { LoanID: '2', LoanName: '201 Sample', LoanAmount: '150000000'},
                    ];
                }
            };
        });

        myModule.controller('overview', function($scope, $compile, loanRepository){
            $scope.loans = loanRepository.getAllloans();

            $scope.compileOverview = function(){

                $scope.loanOverviewHTML = '';

                angular.forEach($scope.loans, function(loanDetails,loan){
                    $scope.loanOverviewHTML += '<a ng-click="reviewLoan(' + loanDetails.LoanID +')">' + loanDetails.LoanName + '</a>';
                });

                var overviewHTML = $compile($scope.loanOverviewHTML);
                angular.element(document.getElementById("overview")).append(overviewHTML);
            }

        });

index.html

<body ng-app="myModule" ng-controller="overview" ng-init="compileOverview()">
    <div id="overview">

    </div>
</body>

The expected result is that the controller would append the compiled HTML into the view, giving this:

<body ng-app="myModule" ng-controller="overview" ng-init="compileOverview()">
    <div id="overview">
        <a ng-click="reviewLoan(1)">101 Sample</a>
        <a ng-click="reviewLoan(2)">201 Sample</a>
    </div>
</body>

I'm not sure why I'm getting an error for 'appendChild' as I'm using 'append' only. Would love to know why I'm getting this error and why the HTML isn't being injected into the DOM.

6
  • Don't do this...ever. If you absolutely MUST add DOM yourself, do so within a directive, never within a controller. However, this seems like something that could be instead driven by an ng-repeat on <div id="overview"> instead of handling DOM adds yourself. Commented Mar 25, 2016 at 18:29
  • is ng-click"reviewLoan misprint or you missing =? Commented Mar 25, 2016 at 18:31
  • @VladimirFurso that was a typo. Fixed it, thanks for catching :) Commented Mar 25, 2016 at 18:37
  • @DavidL thanks for the comment. This is a smaller sample of a much larger project - I'm keeping the logic out of the view because it's not as scalable as I would like. Any suggestions on how to go about this using a directive? The concept still confuses me quite a bit. Commented Mar 25, 2016 at 18:41
  • 1
    @fireinspace there is an error in that string var overviewHTML = $compile($scope.loanOverviewHTML); $compile requires scope as parameter. docs.angularjs.org/api/ng/service/$compile It should look like this var overviewHTML = $compile($scope.loanOverviewHTML)($scope); Commented Mar 25, 2016 at 18:48

1 Answer 1

5

As I mentioned in my comment, you can avoid all of the $compile invocation by simply using ng-repeat to render as much or as little html as you need, based on $scope.loans.

<div id="overview" ng-repeat="loan in loans">
    <a ng-click="reviewLoan(loan.LoanID)">{{loan.LoanName}}</a>
</div>

You want to avoid $compile as much as possible, particularly if you want to ever port your application to Angular2 since it doesn't exist there. If you MUST use $compile, it should always be done in a directive, never a controller. However, that's not necessary in this case since we can allow Angular to handle it for us.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.