dance2die
dance2die

Reputation: 36905

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>

Upvotes: 1

Views: 4801

Answers (2)

Milad Mohamadi
Milad Mohamadi

Reputation: 135

You can import template in top of the script and use it as a "template", not "templateUrl":

import area1 from '/templates/area1.html';

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

})();

Upvotes: 0

Shyju
Shyju

Reputation: 218722

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");
                    }
                }
            }
        });
})();

Upvotes: 3

Related Questions