DorkMonstuh DorkMonstuh - 6 months ago 64
AngularJS Question

appending html from another file to div using directive

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()

});
};
});

Answer

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.

Comments