1

I am quite new to angularjs, I am trying to append html from another html file using my directive. I only want to do this only if I get a success callback from the server from my http request.

Currently I have my directive, I am not sure if this is the way to do it. I have also attached my directive to the div I want to append to.

host.directive('newHost', function(){
    return {
        restrict:  'E',
        link: function(scope, element, attr){
            scope.newBox = function(){
                 templateUrl: 'newHostTemplate.html';
            };
        }
    }
});

I then call $scope.newBox() on my success callback which at that point I want to append to the div.

I have followed the answer below, and tried to adapt it to my scenario, however I am getting the error $scope.newBox is not a function, here is my current implementation.

    host.directive('newHost', function(){
    return {
        restrict:  'E',
        template: '<div ng-include="getTemplateUrl()"></div>',
        link: function(scope, element, attr){
            scope.newBox = function(){
                console.log('newBox');
                scope.getTemplateUrl = function(){
                    return 'newHostTemplate.html'
                };
            };
        }
    }
});

//controller, this does all the routing on client side
host.controller('hostsController', function($scope, $http, $window, $rootScope){
    $rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
        console.log("failed to change routes");
    });

    $scope.newHost = {};
    $scope.addNewHost = function() {
        $http({
            method  : 'POST',
            url     : 'http://192.168.0.99:5000/newHost',
            data    : JSON.stringify($scope.newHost),  // pass in data as strings
        })
        .success(function(data) {
            console.log(data);
            $scope.newBox()
            //on success we want to close the modal and reset the data
            $scope.newHost = {}
            $scope.dismiss()

        });
    };
});
2
  • Use templateUrl property to set path to template Commented Jun 1, 2016 at 0:30
  • templateUrl must be same level as link, and you have invalid syntax inside inner function. dynamic template can be done with ng-include I think Commented Jun 1, 2016 at 1:58

1 Answer 1

1

Here are two examples:

Using ng-include and a function that points to the external file

I created a plunker showing you a working example. As soon as you click the 'process data' link, it will call NewBox() that will append the content from an external file. This link simulates your callback.

In the directive, the template is defined as template:

<div ng-include="getTemplateUrl()"></div>

And in the link function, I setup getTemplateUrl() once newBox() is called... the getTemplateUrl() function returns the name of the external file (e.g. template.html):

link: function(scope, element, attr) {
    scope.newBox = function() {
        console.log('new Box');
        scope.getTemplateUrl = function() {
            return 'template.html';
        }
    }
}

The full JS file is:

angular.module('components', [])
  .directive('newHost', function() {
    return {
      restrict: 'E',
      template: '<div ng-include="getTemplateUrl()"></div>',
      link: function(scope, element, attr) {
        scope.newBox = function() {
          console.log('new Box');
           scope.getTemplateUrl = function() {
                return 'template.html';
           }
        }
      }

    }
  });

  angular.module('HelloApp', ['components'])
 .controller('MyCtrl', ['$scope', function($scope) {
    $scope.name = 'This is the controller';

    $scope.go = function() {
      console.log('Processing...');
      $scope.newBox();
  }
}]); 

index.html is:

<!doctype html>
<html ng-app="HelloApp" >
<head>
  <meta charset="utf-8">
  <title>AngularJS Plunker</title>
  <link rel="stylesheet" href="style.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
  <script src="app.js"></script>
</head>
<body>
  <div ng-controller="MyCtrl">
    <new-host></new-host>
    <br/>
    <a ng-href='#here' ng-click='go()'>process data</a>

  </div>
</body>
</html>

And template.html is a simple example:

<div>
  This is some content from template.html
</div>

If you look in plunker, once you press 'process data', the template.html content is then added using the newBox() function. Now, you would replace that link with your callback.

Using ng-show and a boolean to hide/show the content

One way which is going in a slightly different direction than you is to use ng-show and hide the template until newBox() is called.

I created a JSFiddle that shows an example of how to do this.

The new-host tag is hidden at the start using ng-show:

<div ng-controller="MyCtrl">
    <new-host ng-show='displayNewHost'></new-host>
    <br/>
    <a ng-href='#here' ng-click='go()' >process data</a>
</div>

The link process data is to simulate your success callback, so when you click on it, it will call $scope.newBox()

Here is the main JS file:

angular.module('components',[])
.directive('newHost', function() {
    return {
        restrict: 'E',

        link: function(scope, element, attr) {
            scope.newBox = function() {
                console.log('new Box');
                scope.displayNewHost = true;
            };
        }

    }
})

angular.module('HelloApp', ['components'])

function MyCtrl($scope) {
    $scope.displayNewHost = false;
    $scope.name = 'This is the controller';

    $scope.go = function() {
        console.log('Processing...');
        $scope.newBox();
    }
}

angular.module('myApp', ['components'])

As you see, in the controller we set displayNewHost to false hiding the directive. Once one clicks on the process data link, the newBox function sets displayNewHost to true and then the content appears.

In your example, you would replace the 'template' by 'templateUrl' pointing to your file.

That is another solution.

Editing my answer to answer the follow-up question / newBox is not a function error

Just reading your code (without checking using plunker so I may be wrong), I am guessing that the problem is that once you are in the success function $scope points to another scope. Try to change your code to this... please note that I put $scope in a variable 'vm' and then use that in both the core function and the success callback.

host.controller('hostsController', function($scope, $http, $window, $rootScope){
    $rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
        console.log("failed to change routes");
    });
    var vm = $scope;
    vm.newHost = {};
    vm.addNewHost = function() {
        $http({
            method  : 'POST',
            url     : 'http://192.168.0.99:5000/newHost',
            data    : JSON.stringify(vm.newHost),  // pass in data as strings
        })
        .success(function(data) {
            console.log(data);
            vm.newBox()
            //on success we want to close the modal and reset the data
            vm.newHost = {}
            vm.dismiss()

        });
    };
});'
Sign up to request clarification or add additional context in comments.

3 Comments

Hi, thanks for your input, I am having problems as I am getting newBox is not a function. I have updated my code above and have tried to adapt your solution to fit my scenario. I was wondering if you could point to me what I have done wrong?
@DorkMonstuh -- I updated my answer see above the section called Editing my answer to answer the follow-up question / newBox is not a function error (at the end of the post.) Without checking in plunker, the error might be that $scope is pointing to a different scope in your callback. I use a variable instead to make sure I am referencing the same scope in the function and the callback. Let me know.
I updated the [plunker example] (plnkr.co/edit/hN8BuECSCcuVCkNH7mrW?p=preview). Because the URL is incorrect, it goes to the error callback and successfully call vm.newBox(); Of course, on your machine it will go through the success callback and call vm.newBox()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.