Calling multiple REST APIs using response of first API in AngularJS - javascript

I am new to AngularJS and trying to make an application which loads data by calling APIs. It is like I am fetching the list of boxes of type A (Resource Groups) and then each Box of type A has multiple boxes of type B (Virtual Machines). So I have been able to fetch all type A boxes and by using each value of type A box, I have been able to fetch all type B boxes(VMs). But now how shall I put the VM's in respective resource group's panel-body.
(function() {
var app = angular.module('AzureManager', []);
app.controller('resourceGroupsController', function($scope, $http) {
$scope.getRGList = function() {
$http.get('/resource-group/all').then(function(response) {
$scope.resourceGroups = response.data.value;
});
};
$scope.getRGList();
});
})();
<!DOCTYPE HTML>
<HTML ng-app="AzureManager">
<head>
<title>Azure Manager</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-rc.1/angular.min.js"></script>
<script src="public/app.js"></script>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#topNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Azure Manager</a>
</div>
<div class="collapse navbar-collapse" id="topNavbar">
<ul class="nav navbar-nav navbar-right">
<li><span class="glyphicon glyphicon-user"></span> Anant
</li>
<li><span class="glyphicon glyphicon-log-out"></span> Logout
</li>
</ul>
</div>
</div>
</nav>
<section class="container-fluid" ng-controller="resourceGroupsController">
<div class="panel panel-default" ng-repeat="RG in resourceGroups" id="{{RG.name}}-resources-container">
<div class="panel-heading">
<div class="panel-title">{{RG.name}}</div>
</div>
<div class="panel-body"></div>
</div>
</section>
</body>
</HTML>

Either call a vms/all endpoint by chaining the calls to resource groups and virtual machines and link the virtual machines to their resource groups after both promises have returned.
Or call a endpoint for each resource group:
$scope.getRGList = function() {
$http.get('/resource-group/all').then(function(response) {
$scope.resourceGroups = response.data.value;
$scope.resourceGroups.forEach(function (rg) {
$http.get('/virtual-machine/'+rg.id).then(function(response) {
rg.vms = response;
}
}
});
};
<section class="container-fluid" ng-controller="resourceGroupsController">
<div class="panel panel-default" ng-repeat="RG in resourceGroups track by RG.id" id="{{RG.name}}-resources-container">
<div class="panel-heading">
<div class="panel-title">{{RG.name}}</div>
</div>
<div class="panel-body">
<div class="vm" ng-repeat="vm in RG.vms track by $index">
{{vm.name}}
</div>
</div>
</div>
</section>

Related

How to change page and maintain the nav bar

i wrote a html script with a simple navbar. The main page is fine but when i click on "About" the page reload and i just want to reload the content and maintain the navbar. I'm using bootstrap. How can i do this?
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse" ng-controller="HeaderController">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Logo</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<!-- <form class="form-horizontal" action="/action_page.php"> -->
<div class="row">
<div class="col-*-10">
<legend><h2>Title</h2></legend>
</div>
</div>
<p>HOME!!!</p>
</div>
</body>
</html>
And this is my about page:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<p>ABOUT!!!!!!!!!!!!!!!!!</p>
</body>
</html>
You're actually supposed to implement such a thing using a router, ui-bootstrap is just a UI library. The ui-router wiki explains how to accomplish this using multiple views per state.
Let's say we have two states in which we want to have a shared navbar, than define 2 states and provide each with 2 views, one navbar and another for the body
Provide each navbar view the same controller and template
$stateProvider
.state('stateA',{
views: {
'navbar#stateA': {
templateUrl: 'navbar.html', // <-- navbar html goes here
controller: 'navbarCtrl'
},
'body#stateA': {
templateUrl: 'report-table.html',
controller: 'StateACtrl'
}
}
})
.state('stateB',{
views: {
'navbar#stateB': {
templateUrl: 'navbar.html',
controller: 'navbarCtrl'
},
'body#stateB': {
templateUrl: 'report-table.html',
controller: 'StateBCtrl'
}
}
})
Inside your markup, you should maintain
<body>
<!-- the router will replace this with your html files -->
<div ui-view="navbar"></div>
<div ui-view="body"></div>
</body>
On the open body tag, make a javascript function named start onLoad="start()" Then within the function set the innerhtml the navbar code.
HTML:
<body onLoad="start()">
<div id="navbar"></div>
</body>
JS:
function start() {
document.getElementById("navbar").innerHTML = "<nav class="navbar navbar-inverse" ng-controller="HeaderController">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Logo</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
</div>
</nav>";
}
There are a couple ways to do this without copying the whole navigation bar into every HTML file.
You can put all of the content in the same page and use JavaScript to hide/show specific sections when you click on the menu link
You can use JavaScript to retrieve the new content via AJAX and update the container.
You can add JavaScript to create the navigation bar on the fly for each page you want it on.

Angular Routing not working and not loading content in ng-view

Following is the folder structure I am using for my demo application
css
fonts
images
js
views
index.html
The code for index.html is as follows :
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Welcome to Sandhu Tutors</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<!-- Top Navigation-->
<nav class="nav navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Menu</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">ABSS</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li>Home</li>
<li>About Us</li>
<li><a ng-href="">First</a></li>
<li><a ng-href="">Second</a></li>
</ul>
</div>
</div>
</nav>
<!--Main view goes here -->
<div ng-view></div>
<footer>
<div class="navbar navbar-inverse navbar-fixed-bottom">
<div class="container">
<div class="navbar-text pull=left">
<p> ABSS © Sandhu 2017.</p>
</div>
</div>
</div>
</footer>
<script src="js/jquery-3.1.1.min.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/angular.min.js"></script>
<script src="js/angular-route.js"></script>
<script src="js/controller.js"></script>
</body>
</html>
And here goes the code for controller.js :
var app = angular.module('myApp',['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/',{
templateUrl : 'views/home.html',
controller : 'homeCtrl'
})
.when('/first',{
templateUrl:'views/first.html',
controller : 'firstCtrl'
})
.when('/second',{
templateUrl:'views/second.html',
controller : 'secondCtrl'
})
.otherwise({
redirect :'/'
});
});
app.controller('homeCtrl',function($scope){
$scope.name="Angad";
});
app.controller('firstCtrl',function($scope){
$scope.name="Second";
});
app.controller('secondCtrl',function($scope){
$scope.name="Second";
});
Routing doesnt seems to work here .... The only error it shows is :
-Error: [$compile:tpload]
-XMLHttpRequest cannot load
Apart from this if anyone could help as to how to make the desired pages open in the ng-view section on the click of the top navbar buttons ...would be highly appreciated !!
Your code seems to be correct. If you are using chrome as a browser use a local webserver to test your site (for example lite-server). Chrome won't allow you to load local files for security reasons. You could also try and test your application with another browser.
Your Navbar hrefs should look like:
<li>About Us</li>
or if you are using AngularJS 1.6
<li>About Us</li>

After clicking submit, Form does nothing

I have been working on a permissions system for my NodeJS (Using the SailsJS MVC) and have ran into a problem. After solving my first error which is outlined here I am now running into an issue where the form does nothing. It does not send an error to console and it does not log an error in the SailsJS console itself. Below is my code.
/**
* GroupsController (API)
*
* #description :: Server-side logic for managing Permissions
* #help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
module.exports = {
update: function(req, res, next) {
var groupObj = {
groupName: req.param('groupName'),
canViewUsers: req.param('canViewUsers'),
canEditUsers: req.param('canEditUsers'),
canPromoteToStaff: req.param('canPromoteToStaff'),
canViewNotes: req.param('canViewNotes'),
canEditPermissions: req.param('canEditPermissions')
};
Groups.update(req.param('id'), groupObj, function groupUpdated(err) {
if (err) {
return res.redirect('/group/edit/' + req.param('id'));
}
res.redirect('/');
});
},
createGroup: function(req, res) {
Groups.create({
groupName: req.param('groupName'),
canViewUsers: req.param('canViewUsers'),
canEditUsers: req.param('canEditUsers'),
canPromoteToStaff: req.param('canPromoteToStaff'),
canViewNotes: req.param('canViewNotes'),
canEditPermissions: req.param('canEditPermissions')
}).exec({
error: function (err) {
return res.negotiate(err);
}
});
}
};
GroupsController (Form)
angular.module('GroupsModule').controller('GroupsController', ['$scope', '$http', 'toastr', function($scope, $http, toastr) {
$scope.groupCreateForm = function(){
// Submit request to Sails.
$http.post('/createGroup', {
groupName: $scope.createGroup.groupName,
canViewUsers: $scope.createGroup.canViewUsers,
canEditUsers: $scope.createGroup.canEditUsers,
canPromoteToStaff: $scope.createGroup.canPromoteToStaff,
canViewNotes: $scope.createGroup.canViewNotes,
canEditPermissions: $scope.createGroup.canEditPermissions
})
.then(function onSuccess(sailsResponse){
window.location = '/groups';
})
.catch(function onError(sailsResponse){
// Handle known error type(s).
// If using sails-disk adpater -- Handle Duplicate Key
var groupAlreadyExists = sailsResponse.status == 409;
if (groupAlreadyExists) {
toastr.error('That group already exists', 'Error');
}
})
}}]);
HTML Form
<!--STYLES-->
<link rel="stylesheet" href="/styles/angular-toastr.css">
<link rel="stylesheet" href="/styles/bootstrap.3.1.1.css">
<link rel="stylesheet" href="/styles/importer.css">
<link rel="stylesheet" href="/styles/style.css">
<link rel="stylesheet" href="/styles/theme.css">
<link rel="stylesheet" href="/styles/theme.min.css">
<!--STYLES END-->
<body ng-app="DashboardModule" ng-controller="DashboardController" ng-cloak>
<div class="bs-docs-section clearfix">
<div class="row">
<div class="bs-component">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<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="/">Insomnia eSports</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><i class="fa fa-users" aria-hidden="true"></i> Group Management </li>
</ul>
<!--
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
-->
<ul class="nav navbar-nav navbar-right">
<li>Sign Out</li>
</ul>
</div>
</div>
</nav>
</div>
</div>
</div>
<form ng-submit="groupCreateForm()" id="create-group-form" class="form-signin" name="createGroup">
<h2 class="form-signin-heading">Create A Group</h2>
<div class="row">
<!-- Group Name -->
<label>Group Name</label>
<input type="text" class="form-control" placeholder="Group Name" name="groupName" ng-model="createGroup.name" ng-maxlength="25" required>
</div>
<!-- Can View Users -->
<div class="row">
<label>View Users?</label>
<input type="checkbox" name="canViewUsers" ng-model="createGroup.canViewUsers">
</div>
<!-- Can View Users -->
<div class="row">
<label>Edit Users?</label>
<input type="checkbox" name="canEditUsers" ng-model="createGroup.canEditUsers">
</div>
<!-- Can Promote To Staff -->
<div class="row">
<label>Promote to Staff?</label>
<input type="checkbox" name="canPromoteToStaff" ng-model="createGroup.canPromoteToStaff">
</div>
<!-- Can Promote To Staff -->
<div class="row">
<label>Can view notes?</label>
<input type="checkbox" name="canViewNotes" ng-model="createGroup.canViewNotes">
</div>
<!-- Can Promote To Staff -->
<div class="row">
<label>Can edit permissions?</label>
<input type="checkbox" name="canEditPermissions" ng-model="createGroup.canEditPermissions">
</div>
<br/>
<!-- Disable signup button until the form has no errors -->
<button class="btn btn-success btn-lg btn-block" type="submit" ng-disabled="createGroup.$invalid">
<span>Create Group</span>
</button>
<input type="hidden" name="_csrf" value="<%= _csrf %>" />
</form>
<!--SCRIPTS-->
<script src="/js/dependencies/sails.io.js"></script>
<script src="/js/dependencies/angular.1.3.js"></script>
<script src="/js/dependencies/Base64.js"></script>
<script src="/js/dependencies/angular-toastr.js"></script>
<script src="/js/dependencies/compareTo.module.js"></script>
<script src="/js/public/signup/SignupModule.js"></script>
<script src="/js/public/groups/GroupsModule.js"></script>
<script src="/js/private/dashboard/DashboardModule.js"></script>
<script src="/js/public/homepage/HomepageModule.js"></script>
<script src="/js/private/dashboard/DashboardController.js"></script>
<script src="/js/public/groups/GroupsController.js"></script>
<script src="/js/public/homepage/HomepageController.js"></script>
<script src="/js/public/signup/SignupController.js"></script>
<!--SCRIPTS END-->
</body>
You don't have the right ng-controller attached to your form, so the $scope.groupCreateForm shouldn't even be getting called. Try adding ng-controller="GroupsController" to your form and try again.
<form ng-controller="GroupsController" ng-submit="groupCreateForm()" id="create-group-form" class="form-signin" name="createGroup">
I fixed the issue with the following code
<body ng-app="GroupsModule" ng-controller="GroupsController" ng-cloak>
I had the wrong app and controller defined. Thank you to Fissio for sparking the idea that this was the problem.

ng-click not working in MVC partial view

I have a single page application using angular.js and MVC.
The page calls two partial views:
Menu
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>© #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())
{
#menuItem.Parent.Name<b class="caret"></b>
}
else
{
#menuItem.Parent.Name
}
#if (menuItem.Children != null && menuItem.Children.Any())
{
<ul class="dropdown-menu multi-level">
#foreach (var sub in menuItem.Children)
{
<li>
#sub.ChildMenuName
</li>
}
</ul>
}
</li>
</ul>
}
<ul class="nav navbar-nav navbar-right">
<li>{{currentModule}}</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">
Account number: #account.AccountNumber
</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>
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));
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())
{
#menuItem.Parent.Name<b class="caret"></b>
}
else
{
#menuItem.Parent.Name
}
#if (menuItem.Children != null && menuItem.Children.Any())
{
<ul class="dropdown-menu multi-level">
#foreach (var sub in menuItem.Children)
{
<li>
#sub.ChildMenuName
</li>
}
</ul>
}
</li>
</ul>
}
<ul class="nav navbar-nav navbar-right">
<li>{{currentModule}}</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">
Account number: #account.AccountNumber
</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>");
};
});

Angular.js Model-View-Controller Dynamic Updates Not Working

AngularJS v1.2.0rc1
I have setup an angular Model-View-Controller. It is accurately requesting data from my database and displaying the values on the html page. However, the problem I am having is when the data I am requesting changes from the current value being displayed, it is not updating the html view.
Code
Controller
var API_ORDER_ROUTE = '/api/stats';
function feedingStatsCtrl($http, $scope) {
$http.get(API_ORDER_ROUTE).success(function(data, status, headers, config) {
if (data.error) {
$scope.error = data.error;
} else {
$scope.current = data.current;
$scope.average = data.average.toFixed(2);
$scope.days_left = data.days_left ? data.days_left : 0;
$scope.days_remaining = Math.min($scope.days_left / 30 * 100.0, 100);
} // EOF else
}).error(function(data, status, headers, config) {
$scope.error = "Error fetching order statistics.";
});
}
UPDATE INCLUDING HTML CODE
HTML
<!DOCTYPE html>
<html lang="en" ng-app>
<head>
<meta charset="utf-8">
<title><%= title %></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://d396qusza40orc.cloudfront.net/startup/code/jquery.js"></script>
<script src="https://d396qusza40orc.cloudfront.net/startup/code/bootstrap.js"></script>
<script src="js/angular.min.js" ></script>
<script src="js/controllers.js"></script>
<script src="js/google-analytics.js"></script>
<script src="https://coinbase.com/assets/button.js"></script>
<script src="js/coinbase-post-payment.js"></script>
<link rel="stylesheet" href="https://d396qusza40orc.cloudfront.net/startup%2Fcode%2Fbootstrap-combined.no-icons.min.css">
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/3.0.2/css/font-awesome.css">
<link rel="stylesheet" href="https://d396qusza40orc.cloudfront.net/startup%2Fcode%2Fsocial-buttons.css">
<link rel="stylesheet" href="css/bitstarter-styles.css">
</head>
<body>
<!-- Mobile-friendly navbar adapted from example. -->
<!-- http://twitter.github.io/bootstrap/examples/starter-template.html -->
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" class="btn btn-navbar"
data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="brand" href="#"><%= name %></a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active">Home</li>
<li>LedTest</li>
<li>Orders</li>
<li>Contact</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- We use row-fluid inside containers to achieve a resizable layout. -->
<!-- blogs.endjin.com/2013/04/tips-for-implementing-responsive-designs-using-bootstrap/ -->
<!-- http://stackoverflow.com/a/12270322 -->
<div class="container">
<!-- Font and paired font of .heading/.subheading and body from Google Fonts -->
<!-- www.google.com/fonts/specimen/Ubuntu -->
<!-- www.google.com/fonts/specimen/Ubuntu#pairings -->
<div class="row-fluid heading">
<div class="span12">
<h1><%= product_name %></h1>
</div>
</div>
<div class="row-fluid subheading">
<div class="span12">
<!-- Special typography from Bootstrap for lead paragraph. -->
<!-- http://twitter.github.io/bootstrap/base-css.html#typography -->
<p class="lead"><%= product_short_description %></p>
</div>
</div>
<div class="row-fluid pitch">
<div class="span5 offset1 video">
<img class="img-polaroid" src="img/480x300.gif">
</div>
<!-- We define a new 'actions' div to contain statistics, order, and share buttons.-->
<div class="span5 actions" ng-controller="feedingStatsCtrl">
<div class="row-fluid">
<div class="span8 offset2">
<div class="row-fluid statistics">
<div ng-show="!error">
<div class="span4">
<!-- linediv-l and linediv-r give dividing lines that look
different in horizontal and vertical layouts, illustrating
media queries. -->
<div class="linediv-l">
<h3>{{current}}</h3> <p>Current</p>
</div>
</div>
<div class="span4">
<div class="linediv-c">
<h3>{{average}}</h3> <p>Average</p>
</div>
</div>
<div class="span4">
<div class="linediv-r">
<h3>{{days_left}}</h3> <p>Days Left</p>
</div>
</div>
</div>
<div ng-show="error">
<h3>{{error}}</h3>
</div>
</div>
</div>
<div class="row-fluid" ng-show="!error">
<div class="span10 offset1">
<!-- Bootstrap progress bar -->
<!-- http://twitter.github.io/bootstrap/components.html#progress -->
<div class="thermometer progress active">
<div class="bar bar-success" ng-style="{'width': days_remaining+'%'}"></div>
<div class="bar bar-warning" ng-style="{'width': (100-days_remaining)+'%'}"></div>
</div>
</div>
</div>
I know the data is being requested properly. When I refresh the browser it correctly updates the three variables I am pulling from the DB. I just can't figure out why the Angular controller is not dynamically updating. Can any provide some guidance?
You may make a common mistake: try to refer a primitive variable from parent scope, in Angular, child scope can not refer a primitive type variable defined in parent scope (string, number, bool...etc), any primitive reference would create a separate variable in child scope with same value. So even $scope.current changed in parent scope, the variable in child scope won't change.
further reading about scope
You can use object to avoid this happened:
var API_ORDER_ROUTE = '/api/stats';
function feedingStatsCtrl($http, $scope) {
$scope.result = {};
$http.get(API_ORDER_ROUTE).success(function(data, status, headers, config) {
if (data.error) {
$scope.result.error = data.error;
} else {
$scope.result.current = data.current;
$scope.result.average = data.average.toFixed(2);
$scope.result.days_left = data.days_left ? data.days_left : 0;
$scope.result.days_remaining = Math.min($scope.days_left / 30 * 100.0,100);
} // EOF else
}).error(function(data, status, headers, config) {
$scope.result.error = "Error fetching order statistics.";
});
}
In template:
<div class="span8 offset2">
<div class="row-fluid statistics">
<div ng-show="!error">
<div class="span4">
<!-- linediv-l and linediv-r give dividing lines that look
different in horizontal and vertical layouts, illustrating
media queries. -->
<div class="linediv-l">
<h3>{{result.current}}</h3> <p>Current</p>
</div>
</div>
<div class="span4">
<div class="linediv-c">
<h3>{{result.average}}</h3> <p>Average</p>
</div>
</div>
<div class="span4">
<div class="linediv-r">
<h3>{{result.days_left}}</h3> <p>Days Left</p>
</div>
</div>
</div>
<div ng-show="error">
<h3>{{result.error}}</h3>
</div>
</div>
</div>

Categories