Sung Sung - 4 months ago 34
Javascript Question

AngularJS directive: "templateUrl" doesn't work while "template" works

I have an AngularJS directive named,

areaOne
. When I use
template
the template is displayed but when I use
templateUrl
in area1.js, template HTML is not rendered.

What am I missing here?

Server side: ASP.NET MVC 5

Client side: AngularJS 1

Source code is available here on github.

Project structure:

Root
Scripts
app.js
directives
area1.js
templates
area1.html
Views
Home
Index.cshtml


Index.cshtml

@{
ViewBag.Title = "Index";
}
@section Scripts{
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/app.js"></script>
<script src="~/Scripts/directives/area1.js"></script>
}
<h2>Index</h2>
<div ng-app="app">
<area-one></area-one>
</div>


app.js

(function() {

angular.module("app", []);

})();


area1.js

(function() {
angular.module("app")
.directive("areaOne", function() {
return {
restrict: 'E',
templateUrl: '~/templates/area1.html',
controller: function ($scope) {
$scope.button1Click = function () {
alert("button1 clicked");
}
}
}
});
})();


area1.html

<div>
<button id="button1" ng-click="button1Click()">Button 1</button>
</div>

Answer

Edit

If you simply care about getting the root/base url of the site so you can append that to get the other url you are after, you may simply use / as the first character of your url.

var getUsersUrl = "/api/users";

Alternate Approach to build the relative url using the MVC helper methods.

Because the template url path is wrong! Javascript cannot convert your ~ to app base path like razor do. You should be able to see a 404 error if you inspect your browser network tab.

You should not hard code your app base path like that. You may use the Url.Content or Url.RouteUrl helper methods in your razor view to generate the url to the app base. It will take care of correctly building the url regardless of your current page/path.Once you get this value, assign it to a javascript variable and use that in your other js code to build your other urls. Always make sure to use javascript namespacing when doing so to avoid possible issues with global javascript variables.

So in your razor view (Layout file or specific view), you may do this

<script>
    var myApp = myApp || {};
    myApp.Urls = myApp.Urls || {};
    myApp.Urls.baseUrl = '@Url.Content("~")';       
</script>
<script src="~/Scripts/AngularControllerForPage.js"></script>
<script>
    var a = angular.module("app").value("appSettings", myApp);
</script>

And in your angular controllers/files, you can access it like,

var app = angular.module("app", []);
var ctrl = function (appSettings) {

    var vm = this;

    vm.baseUrl = appSettings.Urls.baseUrl;
    //build other urls using the base url now
    var getUsersUrl = vm.baseUrl + "api/users";
    console.log(getUsersUrl);

};
app.controller("ctrl", ctrl)

You can and should access this in your data services, directives etc.

(function () {
    angular.module("app")
        .directive("areaOne", function (appSettings) {           
            return {
                restrict: 'E',
                templateUrl: appSettings.Urls.baseUrl+'/templates/area1.html',
                controller: function ($scope) {
                    $scope.button1Click = function () {
                        alert("button1 clicked");
                    }
                }
            }
        });
})();
Comments