Variable not being displayed in DOM, yet ng-repeat works - angularjs

I was setting up a very basic AngularJS + Ionic app, and encountered a weird case where despite the ng-repeat working properly (e.g repeating the correct number of times), the variables weren't rendered on the DOM. Additionally, I saw this weird behavior only happening in my local app, but working properly on an exact copy on Plunker.
On app.js I have:
angular.module('sleepExpertChatApp', [
'ionic',
])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('peoplelist', {
url: '/peoplelist',
templateUrl: 'templates/people-list.html',
controller: 'PeopleListCtrl'
});
$urlRouterProvider.otherwise('/peoplelist');
})
.controller('PeopleListCtrl', function($scope){
$scope.obj = {}
$scope.test = "Mytestvar"
$scope.obj.people = [{name:"leon"},{name:"jeff"},{name:"leon"}];
console.log($scope.obj);
});
And my html:
<!DOCTYPE html>
<html ng-app="sleepExpertChatApp">
<head>
<script src="http://code.ionicframework.com/1.0.0/js/ionic.bundle.js"></script>
<script src="https://cdn.firebase.com/js/client/2.2.4/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/1.1.1/angularfire.min.js"></script>
<script src="/static/chat/main.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.ionicframework.com/1.0.0/css/ionic.min.css">
</head>
<body>
<ion-nav-view></ion-nav-view>
<script id="templates/people-list.html" type="text/ng-template">
<ion-view id="userMessagesView"
view-title="People">
afsdf
<ion-content>
<div ng-repeat="person in obj.people">
<div class="item">
{{person.name}}
</div>
</div>
</ion-content>
</ion-view>
</script>
</body>
</html>
This is the Plunker: http://plnkr.co/edit/UV3AJoEFpUeE45DkVv9A
Locally, the simple ng-repeat does produce the right number of elements, but when trying to evaluate the expression to display the variables, nothing is shown. See the below screenshot and notice that there are 3 divs with class item, as expected, but they have no name.
Any ideas what could be going wrong in this seemingly trivial set up?

Ah! I didn't realize I was serving the HTML from a Django server, and so Django's template rendering engine was clashing with AngularJS's.
Simply wrapping my HTML with Django's {% verbatim %} tag fixed my problem.

Related

AngularJS ngRoute not working as expected

I'm trying to use the ngRoute in my angularJS page, but I'm not able to load my content within ng-view.
HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
<link href="CSS/index.css" rel="stylesheet" />
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-route.js"></script>
<script src="Scripts/app/index.js"></script>
</head>
<body ng-app="app">
<header>
<a ng-href="#/add-new">Add new</a>
</header>
<div ng-view></div>
<footer>
#Copyright 2017
</footer>
</body>
</html>
index.js:
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/add-new', {
template: 'Some content'
})
}]);
Not sure what I'm missing here.
If I add otherwise condition on $routeProvider, it gets loaded. Please let me know what am I missing here so that the content within my $routeProvider.when gets loaded in my ng-view on markup. Thanks
Also not getting any console errors.
try this
JS:
app.config(function($routeProvider) {
$routeProvider
.when("/", {
templateUrl : "index.htm"
})
.when("/add-new", {
templateUrl : "add.htm"
})
});
HTML:
Red
Add this below line in your HTML page
<base href="/">
and change ng-href to href
EDIT :
$location in HTML5 mode requires a <base> tag to be present!
If you using ng-href, the you should pass $scope object
You don't have entry point for the app, so if you load your app and you are not going to specific url you will not see any results.
You can add otherwise({redirectTo:'/add-new'}) or go to #/add-new to see your page

Why does this code break once "app" and the ng-controller are added?

This code is virtually verbatim from egghead.io, but it is not working at all unless I remove ="app" and remove the ng-controller attribute from the <body> element. (And of course the last <script> element gets ignored in the process—the code that would normally be in app.js.) Of course removing those bits prevents anything else from working or being added.
<!doctype html>
<html ng-app="app">
<head>
<script src="http://code.angularjs.org/angular-1.0.0.min.js"></script>
<script src="http://code.angularjs.org/angular-ui-router-1.0.0.min.js"></script>
<script>
angular.module('app', ['ui.router'])
.controller("FirstCtrl", function FirstCtrl() {
var first = this;
first.greeting = "First";
});
</script>
</head>
<body ng-controller="FirstCtrl as first">
<div>
<input type="text" ng-model="first.greeting" placeholder="First Name">
<hr>
<h1>{{ first.greeting }} World!</h1>
</div>
</body>
</html>
Here's similar code on JSFiddle. (It's only similar because JSFiddle imposes constraints that make it impossible to post identical code. It has the same problem, so I assume the differences are insignificant for tracking down the source of the bug.)
Where is the bug? Why is this not working?
With latest angular dependency it worked for me.
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.min.js"></script>
<script>
angular.module('app', ['ui.router'])
.controller("FirstCtrl", function FirstCtrl() {
var first = this;
first.greeting = "First";
});
</script>
</head>
<body ng-controller="FirstCtrl as first">
<div>
<input type="text" ng-model="first.greeting" placeholder="First Name">
<hr>
<h1>{{ first.greeting }} World!</h1>
</div>
</body>
</html>
You are using angular ui-router but not using it the way you are supposed to be. Check the documentation here to get a clearer idea. Angular UI router loads its contents in a container containing ui-view attribute. As per documentation
AngularUI Router is a routing framework for AngularJS, which allows you to organize the parts of your interface into a state machine. Unlike the $route service in Angular core, which is organized around URL routes, UI-Router is organized around states, which may optionally have routes, as well as other behavior, attached.
You need to load different states in your ui-view and also pass values in different states in the process. You need to add dependencies for $stateProvider and $urlRouterProvider in your app config for a completely functional angular ui router implementation. This being told what you need to do is like below -
And also check out the working example in PLUNKER
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<title>AngularJS: UI-Router Quick Start</title>
<!-- Bootstrap CSS -->
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="container">
<div class="row">
<div class="span12">
<div class="well" ui-view></div>
</div>
</div>
<!-- Angular -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.js"></script>
<!-- UI-Router -->
<script src="//angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<!-- App Script -->
<script>
var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider, $urlRouterProvider){
// For any unmatched url, send to /route1
$urlRouterProvider.otherwise("/route1")
$stateProvider
.state('route1', {
url: "/route1",
templateUrl: "route1.html",
controller: function($scope) {
$scope.greeting = "First";
}
})
})
</script>
</body>
</html>

templateUrl for AngularJS (routing)/MVC application never loads templates

We are attempting to create a MVC/AngularJS mini-SPA site using various links found on tutorial sites and others like: AngularJS routing in MVC application with templates. However, clicking on the links appear to load the whole page every time, and the templates are never loaded. I am sure I'm missing something simple, but can't figure it out.
My _Layout.cshtml looks like:
<!DOCTYPE html>
<html ng-app="registrationModule">
<head>
<meta charset=" utf-8" />
<meta name="viewport" content="width=device-width" />
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
<script src="~/Scripts/angular.min.js"></script>
<script src="~/Scripts/angular-resource.min.js"></script>
<script src="~/Scripts/angular-route.min.js"></script>
<script src="~/GrextScripts/registration-module.js"></script>
<script src="~/GrextScripts/user-repository.js"></script>
<script src="~/GrextScripts/user-controller.js"></script>
#RenderSection("SectionInHeader", required: false)
</head>
<body>
<header>
<div class=" content-wrapper">
<div class="float-left">
<p class="site-title">
GREXT
</p>
</div>
<div class="float-right">
<nav>
<ul id="menu">
<li>Home</li>
<li>Users</li>
</ul>
</nav>
</div>
</div>
</header>
#RenderBody()
#RenderSection("scripts", required: false)
</body>
</html>
The ControlPanel/Index.cshtml (the {{5+5}} renders properly as a "10" on the page, this was just to see if the AngularJS was working
#{
}
<div ng-view>
{{5+5}}
</div>
registration-module.js
var registrationModule = angular.module("registrationModule", ["ngRoute", "ngResource"])
.config(function($routeProvider, $locationProvider) {
$routeProvider.when("/ControlPanel/Users", {
templateUrl: "/templates/users/all.html",
controller: "userController"
});
$locationProvider.html5Mode(true);
});
user-controller.js
registrationModule.controller("UserController", function($scope, userRepository, $location) {
$scope.users = userRepository.get();
});
And last, the template: /templates/users/all.html
{{1+1}}
<table>
<tr><td>User Name</td></tr>
<tr ng-repeat="user in users">
<td>{{user.UserName}}</td>
</tr>
</table>
As mentioned, when I click on the Users link in the page, the whole page reloads and the template all.html is not loaded as I expect it.
#aaronfrost's comment made me re-check my javascript console more thoroughly and found that I need to include a
<base href="/" />
in the < head> tag of my document. Adding this causes everything to work.
Not sure, but the problem may be that you declared the controller as "UserController" with a capital "U", but in the routeProvider you specified it with a lowercase "u" as "userController".
I am guessing that you have an error in the console, so you might want to check there.
Change the routeProvider to use "UserController" instead of "userController" and it should work.

How to hide and show templates rather than destroy and reinject them everytime

I am using ui-router and Named views. it works flawlessly but it doesn't suit my purpose. I don't want the templates to be injected everytime i click on the menu item but only the first time it is clicked after application is loaded. The remaining times, it should simply hide the template and show the template that is currently active for a menu click. when coming back to the original menu click, it should just do ngShow="true" for the hidden template and hide the current one. Is that possible to do without editing the cleanupLastView() in the angular-ui-router?
If i comment out the cleanupLastView(), it simply keeps on injecting templates and does nothing to older templates. So both end up showing. Tried to debug the cleanupLastView() but i couldn't figure out what variables are available to me there so i could re-show what ever is clicked a second time rather than inject again.
index.html
<!DOCTYPE html>
<html lang="en">
<head ng-app="myApp">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="style.css" rel="stylesheet">
<script type="text/javascript" src=".lib/angular-1.3.0/angular.js"></script>
<script type="text/javascript" src="./angular-ui-router.js"></script>
<script type="text/javascript" src="./modular/ct-ui-router-extras.core.js"></script>
<script type="text/javascript" src="./modular/ct-ui-router-extras.dsr.js"></script>
<script type="text/javascript" src="../timerService.js"></script>
<script type="text/javascript" src="../dataService.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<div class="navbar navbar-default navbar-static-top" role="navigation">
<ul class="nav navbar-nav">
<li ng-class="{active: $state.includes('main')}"><a ui-sref="home">Main</a></li>
<li ng-class="{active: $state.includes('files')}"><a ui-sref="files">Files</a></li>
</ul>
</div>
<div>
<div ui-view="pane"></div>
</div>
</div>
</body>
</html>
app.js
var myApp = angular.module("myApp", [ 'ui.router', 'ct.ui.router.extras.dsr']);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state('main',
url:"/main",
deepStateRedirect: true,
views : {
pane: {
templateUrl : 'tpl.pane-0.html'
},
}
)
.state('files',
url: '/files',
deepStateRedirect: true,
views : {
pane : {
templateUrl : 'tpl.pane-1.html'
},
'first#files' : {
templateUrl : 'tpl1.first.html',
deepStateRedirect: true
},
'second#files' : {
templateUrl : 'tpl1.second.html',
deepStateRedirect: true
},
},
)
});
tpl.pane-0.html
<div>
<input type='text'></input>
</div>
tpl.pane-1.html
<div >
<div data-ui-href='first'></div>
<div data-ui-href='second'></div>
</div>
tpl1.first.html
<div>
<input type='text'></input>
</div>
tpl1.second.html
<div>
Second
</div>
This is the simplified code of my app. it works to do the multiple named views but fails at deepStateRedirect which seems to be the one associated with nav bar type of templates rather than(?) Sticky. Is that correct? I added the param deepStateRedirect: true to allthe views being injected but to no avail. if the tpl1.first.html's input text box is written and the view switched to main, and come back, there is no text to be found in the input box. What am i doing wrong?
Yes, you can do this but it requires some custom work.
Change the state so that it uses an empty template.
In the state's controller check if the document already contains the HTML for the view (use a unique ID).
If required, use the $template cache and $compile to create the original template view and append it to the document body.
In the template, you can use ng-show="isState_expression | isState" expression to toggle the visibility of the template.
Basically the ui-routes work the same as before, but you're handling the compiling of the template yourself. Once it's in the DOM (not inside the ui-view). You can just leave it there to be handled by ng-show.
I don't recommend using resolve on the state since it's going to become a static state.
Here's the manual on $compile:
https://docs.angularjs.org/api/ng/service/$compile
Here's a tutorial on $compile:
http://www.benlesh.com/2013/08/angular-compile-how-it-works-how-to-use.html
Here's a stack answer on $compile:
Compiling dynamic HTML strings from database
Why doesn't it suit your needs? Do you need to preserve the states when they are not shown?
If so, perhaps you should look into UI Router Extras Sticky States. It allows you to preserve the $scope of a state and not create/destroy it every time. This would be better than trying to reinvent the wheel.
Take a look at the sample.

AngularJS - Templates : ngInclude directive

My templates contain JS, as they are called JS is not executed, you have an idea please.
For example in my JS file script.js, i have methods that apply to HTML elements in my templtes and it does not work, an idea please.
Example :
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body ng-app>
<ng-include src="'header.html'"></ng-include>
<script src="angular.js"></script>
<script src="jquery.js"></script>
<script src="script.js"></script>
</body>
</html>
header.html
<div id="header">
<div id="logo">AngularJs</div>
<div id="nav"></div>
</div>
script.js
$(document).ready(function(){
$('#nav').html('<ul><li><a href="">Link<a></li></ul>');
});
The script execute well, I feel it does not find the element div#nav.
The solution provided by Youssef can be made "more Angular", and it will not require jQuery:
<!-- template2.html -->
<script type="text/ng-template" id="template2.html">
<p ng-class="color">Content of template2.html</p>
</script>
$scope.myFunction = function() {
$scope.color = 'red';
}
http://jsfiddle.net/mrajcok/MfHa6/
In the Angular world, we try to change model properties (e.g., $scope.color) and let the view update automatically. We try to not look up elements by ID or jQuery selectors, and we try to avoid DOM manipulation in the controller -- e.g., $('#tpl2').addClass('red');
Sorry, I read wrong a part of your question, my mistake.
The DOM ready statement of jQuery will probably not work correctly. What you can do is on your ngInclude tag add a onload="FUNCTION_NAME" that contains the DOM edition you indicated inside the script.js
For more information have a look at the documentation here: http://code.angularjs.org/1.0.1/docs-1.0.1/api/ng.directive:ngInclude
--- Old Post ---
#YoussefElMontaser, you don't have to put the quotes on the ngInclude:
<ng-include src="header.html"></ng-include>
probably that is what is wrong with your script not going forward.
Let me know if that worked.
I found the solution:
http://jsfiddle.net/esjeY/
HTML
<div ng-app="">
<div ng-controller="Ctrl">
<select ng-model="template" ng-options="t.name for t in templates">
<option value="">(blank)</option>
</select>
url of the template: <tt>{{template.url}}</tt>
</div>
<div ng-include src="template.url" onload='myFunction()'></div>
</div>
JS
function Ctrl($scope) {
$scope.templates = [{
name: 'template1.html',
url: 'template1.html'
}, {
name: 'template2.html',
url: 'template2.html'
}];
$scope.template = $scope.templates[0];
$scope.myFunction = function() {
$('#tpl2').addClass('red');
}
}
#guiligan : Thanks for your help.

Resources