2

I have a single page application using angular.js and MVC.

The page calls two partial views:

  1. Menu
  2. Accounts

Menu loads fine and when the user clicks a menu item I call another partial view using angular ng-click and inject the partial view result in the main page.

The problem is my ng-click event on the accounts partial view will not fire no matter what i try:

1)Main SPA page:

<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Angular</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body ng-app="myApp" ng-controller="appController">
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            @Html.Action("GetMenu", "Menu")
        </div>
    </div>
    <div class="row">
        <div class="col-md-2" style="background-color:#428bca;height:300px;"></div>
        <div class="col-md-8" id="body">
        </div>
        <div class="col-md-2" style="background-color:#428bca;height:300px;"></div>
    </div>
    <footer>
        <p>&copy; @DateTime.Now.Year</p>
    </footer>
</body>
</html>

2)_Menu partial view:

@model List<DTO.Menu.NavMenuViewModel>

<div class="container top-space scroll">
    <div class="navbar navbar-default navbar-fixed-top" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">Home</a>
            </div>
            <div class="collapse navbar-collapse">
                @{
                    foreach (var menuItem in Model)
                    {
                        <ul class="nav navbar-nav">
                            <li>
                                @if (menuItem.Children != null && menuItem.Children.Any())
                                {
                                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">@menuItem.Parent.Name<b class="caret"></b></a>
                                }
                                else
                                {
                                    <a href="#">@menuItem.Parent.Name</a>
                                }
                                @if (menuItem.Children != null && menuItem.Children.Any())
                                {
                                    <ul class="dropdown-menu multi-level">
                                        @foreach (var sub in menuItem.Children)
                                        {
                                            <li>
                                                <a href="#" ng-click="Navigate($event)">@sub.ChildMenuName</a>
                                            </li>
                                        }
                                    </ul>
                                }
                            </li>
                        </ul>
                    }
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="#" class="navbar-brand">{{currentModule}}</a></li>
                    </ul>
                }
            </div>
        </div>
    </div>
</div>

<script type="text/javascript">
    var app = angular.module('myApp', []);
    app.controller('appController', function ($scope, $http, $compile) {

        alert('loaded the menu controller');

        $scope.Navigate = function (event) {

            $("#body").empty();

            $scope.currentModule = "Current module - " + event.target.innerHTML;

            $http.get("/Account/GetAccounts").success(function (response) {

                $("#body").append(response);
                var el = angular.element('#accounts');
                $compile(el)($scope);

            }).error(function (data, status, headers, config) {
            });
        };
    });
</script>

3)_Accounts partial view:

@model List<DTO.Account>

<div id="accounts">
    @foreach (var account in Model)
    {
        <div class="row">
            <div class="col-md-2">
                <a href="#" ng-click="Click()">Account number: @account.AccountNumber</a>
            </div>
            <div class="col-md-2">Account holder: @account.AccountHolderName</div>
        </div>
    }
</div>
<script type="text/javascript">

    alert('loading accounts js');

    angular.module("myApp").controller("appController", function ($scope) {

        alert('loaded the accounts controller');

        $scope.Click = function () {
            alert("click");
        };
    });
</script>
14
  • Are you using an Angular friendly method to inject your partial views? It sounds like Angular isn't binding properly to the ng-directives after injection. This answer may help: stackoverflow.com/a/30124237/2892948 Commented Mar 26, 2016 at 18:49
  • Doesn't show how you do this injection of partial. Also hard to see why you are even using angular since it isn't doing any of the heavy lifting it is designed for Commented Mar 26, 2016 at 18:54
  • @charlietfl please see my update Commented Mar 26, 2016 at 18:59
  • Problem is you need to use $compile on the html before you append it. Again...are you sure you really need angular since you aren't doing much with it? Commented Mar 26, 2016 at 19:01
  • partial views need to be decleared like <script type="text/ng-template" id="partial/name.html" and to change you need to use ng-route or change the templateURL Commented Mar 26, 2016 at 19:02

2 Answers 2

1

I don't have 50 reputation to comment your question but try first add html to dom

$("#body").append(response);

then get element by class or id and compile.

var el = angular.element('#account');
$compile(el)($scope);

if this not help try this

$("#body").append($compile(angular.html(response).contents())($scope));
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you, I've tried your approach.Not getting any errors in the console but when I click the link to call AccClick() nothing happens.The ng-click is not getting fired
Add alert or console.log in accController we will check controllers is running. Update your menu controller im question.
@DenisWessels move angular.module("myApp").controller("accController", function ($scope) { $scope.AccClick = function (event) { alert("click fired"); }; }); to head section maybe controller start running
please have a look at my update.I've included the main SPA page,menu and accounts partial views.The alert('loaded the accounts controller'); is not being called in the _Accounts partial view.Do you know what I can change to make it work?
@DenisWessels angular is not loading controller, you can try this stackoverflow.com/a/29756657/3037869 or move this controller to menu paritals
|
1

This is what I've done to get it working if anyone else is having the same problem:

1)Main SPA Page:

<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/modernizr")
    <script type="text/javascript">
        angular.module('myApp', []);
    </script>
</head>
<body ng-app="myApp">
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
            </div>
            @Html.Action("GetMenu", "Menu")
        </div>
    </div>
    <div class="row">
        <div class="col-md-2">
            <div class="row">
                <div class="col-md-12 text-center">
                   <h3>TREE VIEW PANEL</h3>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12" id="sidePannel">

                </div>
            </div>
        </div>
        <div class="col-md-8" id="body">

        </div>
        <div class="col-md-2">
        </div>
    </div>
</body>
</html>

2)_Menu partial view:

@model List<DTO.Menu.NavMenuViewModel>

<div id="mController" class="container top-space scroll" ng-controller="menuController">
    <div class="navbar navbar-default navbar-fixed-top" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">SASFIN BFS - ONLINE</a>
            </div>
            <div class="collapse navbar-collapse">
                @{
                    foreach (var menuItem in Model)
                    {
                        <ul class="nav navbar-nav">
                            <li>
                                @if (menuItem.Children != null && menuItem.Children.Any())
                                {
                                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">@menuItem.Parent.Name<b class="caret"></b></a>
                                }
                                else
                                {
                                    <a href="#">@menuItem.Parent.Name</a>
                                }
                                @if (menuItem.Children != null && menuItem.Children.Any())
                                {
                                    <ul class="dropdown-menu multi-level">
                                        @foreach (var sub in menuItem.Children)
                                        {
                                            <li>
                                                <a href="#" ng-click="Navigate($event)">@sub.ChildMenuName</a>
                                            </li>
                                        }
                                    </ul>
                                }
                            </li>
                        </ul>
                    }
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="#" class="navbar-brand">{{currentModule}}</a></li>
                    </ul>
                }
            </div>
        </div>
    </div>
</div>
<script src="~/Scripts/Custom/menu.js"></script>
<script src="~/Scripts/Custom/accounts.js"></script>

3)_Account partial view:

@model List<DTO.Account>

<div id="accounts" ng-controller="accountsController">
    @foreach (var account in Model)
    {
        <div class="row">
            <div class="col-md-2">
                <a href="#" ng-click="Click($event)">Account number: @account.AccountNumber</a>
            </div>
            <div class="col-md-2">Account holder: @account.AccountHolderName</div>
        </div>
        <hr />
        <br />
    }
</div>

4)menu.js:

angular.module("myApp").controller('menuController', function ($scope, $http, $compile) {

    $scope.activateView = function (html) {
        $compile(html.contents())($scope);

        if (!$scope.$$phase)
            $scope.$apply();
    };

    $scope.Navigate = function (event) {

        $("#body").empty();
        $("#body").html("<img src='/Images/loading.gif' id='loader' />")

        $("#sidePannel").empty();

        $scope.currentModule = "Current module - " + event.target.innerHTML;

        $http.get("/Account/GetAccounts").success(function (response) {

            var body = angular.element(document.getElementById("body"));
            $("#body").empty();
            body.html(response);

            var mController = angular.element(document.getElementById("mController"));
            mController.scope().activateView(body);
            $("#loader").hide();

        }).error(function (data, status, headers, config) {
            $("#body").empty();
        });
    };

});

5)account.js:

angular.module("myApp").controller("accountsController", function ($scope) {

    $scope.Click = function (event) {
        var accNumber = event.target.innerHTML;
        $("#sidePannel").empty();
        $("#sidePannel").append("<b>" + accNumber + "</b>");
    };

});

1 Comment

I didn't need to call mController.scope().activateView(body) this way. I just used the $scope.activateView(body); directly and that work for me. Thanks! $compile was the trick!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.