AngularJS simple app webpage stops rendering code - javascript

I'm trying to go through an AngularJS tutorial on codeschool.com but as I work through it and refresh my browser to see my progress, at some point in the tutorial the browser always ends up loading a blank webpage and won't load the code anymore. I've attempted the tutorial from the start twice and it happened both times at different points.
I must keep doing something wrong in my code. Has anyone else had this issue or know how to fix it?
I've seen a couple similar questions on here but the answers haven't worked.
Here's the HTML:
<!DOCTYPE html>
<html ng-app='store'>
<head>
<html lang="en-US">
<link rel="stylesheet/css" type="text/css" href="bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
</head>
<body ng-controller="StoreController as store">
<div ng-repeat="product in store.products">
<h1> {{store.product.name}} </h1>
<h2> {{store.product.price}} </h2>
<p> {{store.product.description}} </p>
<button>Add to Cart</button>
</div>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
And here's the JS file:
(function (){
const app = angular.module('store', [ ]);
app.controller("StoreController", function(){
this.product = gems;
});
const gems = [
{
name: "Dodecahedron",
price: 2.95,
description: 'Many sided gem. Would look great in a ring.',
},
{
name: "Pentagonal Gem",
price: 5.95,
description: 'A gem shaped like a pentagon. More expensive and
more shiny',
}
];
})();

Two things: you have a mismatched variable name between your controller and your view and then inside your ng-repeat you are including your controller alias instead of accessing each of the repeated elements directly.
First change this.product = gems; in your controller to this.products = gems; and then change your ng-repeat div to this:
<div ng-repeat="product in store.products">
<h1> {{product.name}} </h1>
<h2> {{product.price}} </h2>
<p> {{product.description}} </p>
<button>Add to Cart</button>
</div>

Related

Multiple controllers working within ngRoute example

I have a small ngRoute example I am trying that to use multiple applications and controllers with. The first app/controller is for the main page, while the second set of app/controller is for the html that ngRoute loads up after pressing a button. However, it doesn't seem to be working. Code below:
Main Module
var app = angular.module("MainModule", ["ngRoute"]);
Main Controller
app.controller("MainController", function ($scope) {
});
app.config(function ($routeProvider) {
$routeProvider
.when('/customers', {
templateUrl: "customers.html",
controller: "CustomerController"
})
});
Customer Module
var CustomerModule = angular.module("CustomerModule", []);
Customer Controller
CustomerModule.controller("CustomerController", function ($scope) {
$scope.Test = "Hey";
$scope.CustomerArray = [
{ "firstName" : "John", "lastName" : "Williams", "Occupation" : "Fireman" },
{ "firstName" : "Louis", "lastName" : "Abrams", "Occupation" : "Policeman" }
]
});
index.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<script src="scripts/MainModule.js"></script>
<script src="scripts/MainController.js"></script>
<link rel="stylesheet" type="text/css" href="MyCSS.css">
</head>
<body>
<div ng-app="MainModule">
<div id="TopDiv">Main Module</div>
<input type="button" value="Load Customers" />
<div ng-view></div>
</div>
</body>
</html>
customers.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="scripts/CustomerModule.js"></script>
<script src="scripts/CustomerController.js"></script>
</head>
<body>
<div ng-app="CustomerModule" ng-controller="CustomerController">
{{Test}}
<ul>
<li ng-repeat="x in CustomerArray">{{x.firstName x.lastName x.Occupation}}</li>
</ul>
</div>
</body>
</html>
Long bits of code there, but hopefully simple code. The output when I press the "Load Customer" button is literally {{Test}} with no array data to follow.
I am just now learning angular, so any help with this issue I would appreciate. I am just doing this for fun, to try to learn. So I suppose the issue is not pressing. :) Thanks!
I wrote out a working example using the code from the question as a base. There are quite a few adjustments that were made, so I will list each piece with a bit of explanation.
It is not necessary for each "page" to have it's own module. However, it is not a bad practice. To support the design you have here of one module for each view, I made the following changes:
Include the CustomerModule as a dependency in the MainModule (MainModule.js):
var app = angular.module("MainModule", ["ngRoute", "CustomerModule"]);
Load ALL scripts in the index.html:
<script src="scripts/MainModule.js"></script>
<script src="scripts/MainController.js"></script>
<script src="scripts/CustomerModule.js"></script>
<script src="scripts/CustomerController.js"></script>
With these changes, the $routeProvider is able to locate the CustomerController and instantiate it during a route change. The customers.html now does not have to create a controller, and can be stripped down to a complete partial. Also, the expression used in customers.html needed to be changed, and broken down into individual expressions for each property.
The final customers.html:
{{Test}}
<ul>
<li ng-repeat="x in CustomerArray">{{x.firstName}} {{x.lastName}} {{x.Occupation}}</li>
</ul>
Complete working sample on plnkr.co: http://plnkr.co/edit/EjwW9Fsc2DPhBejUETwB?p=preview
I'm not sure, but the problem is in your MainModule. It should be like this or so:
var app = angular.module("MainModule", ["ngRoute"]);
When you calling angular.module with only one parameter - it's only trying get module, not create.
And customers.html should only contains parts of you html, not full:
Full customers.html
{{Test}}
<ul>
<li ng-repeat="x in CustomerArray">{{ x.firstName }} {{ x.lastName }} {{ x.Occupation }}</li>
</ul>
And add move customer js files to index.html:
<script src="scripts/MainModule.js"></script>
<script src="scripts/MainController.js"></script>
<script src="scripts/CustomerModule.js"></script>
<script src="scripts/CustomerController.js"></script>
<link rel="stylesheet" type="text/css" href="MyCSS.css">
Hope, it helps.

AngualrJS controller not working

I just began to learn AngularJS by following this youtube video. First part is okay except when it comes to the controller part.
My code is as below (it's the same as in the video)
<html data-ng-app="">
<head>
<script src="angular.min.js"></script>
<script>
function SimpleController($scope) {
$scope.customers = [{
name: 'Kamal',
city: 'York'
}, {
name: 'Sunil',
city: 'DC'
}, {
name: 'Malith',
city: 'Gotham'
}];
}
</script>
</head>
<body>
<div data-ng-controller="SimpleController">Name :
<input type="text" data-ng-model="name" />
</br>
<ul>
<li data-ng-repeat="cust in customers | filter :name | orderBy:'city'">{{cust.name | uppercase}} - {{cust.city}}</li>
</ul>
</div>
</body>
</html>
when I add data-ng-controller="SimpleController" it will not working and give the following error in the console.
Then when I try to post the question in the SO , I tried it in JSfiddle. I added Angular.js and selected onLoad and not working. But when I selected no wrap - in <head> it works fine.
But I can't do that in my local machine so the problem remains as it is.
Can anybody point me to the correct path ?
You need to initialize app:
var app = angular.module("myApp", []);
<div ng-app="myApp" ng-controller="SimpleController">
<!-- ^^^^^ -->
Demo: http://jsfiddle.net/xy23ybzp/2/
Docs: https://docs.angularjs.org/guide/bootstrap
Check Manual Initialization Section in Docs
After getting help from the answers listed here for this question. I got it working. Below is the working code.
<html >
<head>
<script src = "angular.min.js" ></script>
<script>
var app = angular.module("myApp", []);
app.controller("SimpleController",function($scope){
$scope.customers = [
{name :'Kamal',city : 'York'},
{name : 'Sunil',city:'DC'},
{name : 'Malith',city:'Gotham'}
];
});
</script>
</head>
<body >
<div ng-app="myApp" data-ng-controller="SimpleController">
Name :
<input type="text" data-ng-model="name" />
</br>
<ul>
<li data-ng-repeat="cust in customers | filter :name | orderBy:'city'">{{cust.name | uppercase}} - {{cust.city}}</li>
</ul>
</div>
</body>
</html>

Node/Express project using EJS partials and angular: Uncaught ReferenceError: angular is not defined

I feel like I have completely missed something here but I am trying to use ejs partials in a single page angular app. I keep getting a Uncaught ReferenceError: angular is not defined in my partial. I think this may have something to do with using ejs partials instead of using ng-include, however I have not had any luck in playing with that. Any help would be amazing.
app.js
(function(){
var app = angular.module('dashboard', []);
app.controller('ItemController', function(){
this.item = items;
});
//need to loop through items in DB for now using these test objects
var items = [
{
name : 'name1',//query to db for name goes here
stock : '4',//query to db
img : '/images/bb-logo.png'//query to db
},
{
name : 'name2',//query to db for name goes here
stock : '6',//query to db
img : '/images/bb-logo.png'//query to db
}
];
})();
index.ejs
<!DOCTYPE html>
<html lang="en" ng-app="dashboard">
<head>
<meta charset="UTF-8">
<title><%= title %></title>
<link rel="stylesheet" href='/libs/font-awesome/css/font-awesome.css'>
<link rel="stylesheet" href='/libs/foundation/css/foundation.css'>
<link rel="stylesheet" href='/stylesheets/style.css'>
<!-- include angular here -->
<script type="text/javascript" href='/libs/angular/angular.js'></script>
<script type="text/javascript" href='/libs/modernizer/modernizer.js'></script>
<script type="text/javascript" src="/angularApp.js"></script>
</head>
<body>
<% include partials/topbar %>
<div class="row">
<div class="large-6 columns etsy-container">
<% include partials/etsy-container %>
</div>
<div class="large-6 columns">
<% include partials/amazon-container %>
</div>
</div>
</body>
</html>
/amazong-container
<div class='store-container'>
<h1 class="left">Amazon</h1>
<span class="store-utility-icons"><i class="fa fa-refresh right"></i><i class="fa fa-times-circle-o right"></i></span>
<div class="clear"></div>
<% include /item %>
</div>
/item.ejs
<div ng-controller="ItemController as store" >
<div ng-repeat="item in store.items">
<img ng-src="{{item.img}}" />
<p>{{item.name}} <i> Stock level: {{item.stock}}</i></p>
</div>
</div>
The way you include Angular is wrong. You have
<script type="text/javascript" href='/libs/angular/angular.js'></script>
but it should be:
<script type="text/javascript" src="/libs/angular/angular.js"></script>
So you have to use src instead of href. Looks like a typical copy/paste error. So, in the end, this has nothing to do with EJS or using partials, it's just wrong HTML ;-).
PS: Apart from that, you're using single quotes for attributes in HTML. Go with double quotes all the times, as this is the usual and common way to do it.
PPS: The same applies to the line where you try to load Modernizr.

New todo created but not displayed - todos app with EmberJS without ember-data

I am getting started with EmberJS, followed the Screencast. I am trying to do the TODOs app without ember-data.
Following is my HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Ember.js • TodoMVC</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script type="text/x-handlebars" data-template-name="todos">
<section id="todoapp">
<header id="header">
<h1>todos</h1>
{{input type="text" id="new-todo" placeholder="What needs to be done?" value=newTitle action="createTodo"}}
</header>
<section id="main">
<ul id="todo-list">
{{#each}}
<li {{bind-attr class="isCompleted:completed"}}>
<input type="checkbox" class="toggle">
<label>{{title}}</label><button class="destroy"></button>
</li>
{{/each}}
</ul>
<input type="checkbox" id="toggle-all">
</section>
<footer id="footer">
<span id="todo-count">
<strong>2</strong> todos left
</span>
<ul id="filters">
<li>
All
</li>
<li>
Active
</li>
<li>
Completed
</li>
</ul>
<button id="clear-completed">
Clear completed (1)
</button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
</footer>
</script>
<script type="text/javascript" src="js/jquery-1.11.0.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
<script type="text/javascript" src="js/handlebars-v1.3.0.js"></script>
</script><script type="text/javascript" src="js/ember.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
The javascript - all in one place.
window.Todos = Ember.Application.create();
Todos.Router.map(function () {
this.resource('todos', { path: '/' });
});
Todos.TodosController = Ember.ArrayController.extend({
actions:{
createTodo: function(){
var title = this.get('newTitle');
if(!title.trim()){return;}
todos.push({
id: todos[todos.length-1].id +1,
title: title,
isCompleted: false
});
this.set('newTitle','');
}
}
});
Todos.TodosRoute = Ember.Route.extend({
model: function(){
return todos;
}
});
var todos=[{
id: 1,
title: 'Learn Ember.js',
isCompleted: true
},
{
id: 2,
title: '...',
isCompleted: false
},
{
id: 3,
title: 'Profit!',
isCompleted: false
}];
The problem is when I try to add a new todo entry, it is not shown in the UI as added, but when I type todos on the console.
I see the new entry had been added. Why is it that the model is changed but nothing is shown in the UI ?
I also notice that the new entry in the todos array does not have methods like getTitle, setTitle, get isCompleted, set isCompleted that other objects have - which makes me think I am definitely not missing something here.
It seems like I need to get hold of model for TodosRoute and add to it, if that is what I need to do.
How can I do that ?
You have to use todos.pushObject() instead of simple array.push().
Short explanation: "Push the object onto the end of the array. Works just like push() but it is KVO-compliant." http://emberjs.com/api/classes/Ember.MutableArray.html#method_pushObject
Somewhat longer explanation: While Ember extends JS objects like array by default to make them better citizen in Emberland, it doesn't override existing methods like push(). This is why you need to use a separate method (pushObject) - it's Ember's solution to make data binding work on JS objects like an array.
Almost the same goes for plain JS objects: Ember has Ember.Object, which has some methods of it's own, which are not needed when all you need is a classic JS object. That doesn't mean you must use Ember.Object every time, in this case Ember is smart enough to set up data binding for you, based on the properties you access from your Handlebars template.

Angularjs external templating: the template cannot be loaded?

I thought loading an external template with Angularjs is as simple as this below,
<div ng-include='template/index.php'></div>
But it does not print anything out on the browser. What have I missed?
The html,
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Angualr</title>
<meta charset="utf-8">
<script src="js/angular.min.js"></script>
<script src="js/app.js" type="text/javascript"></script>
<script src="js/maincontroller.js" type="text/javascript"></script>
</head>
<body>
<div ng-include='template/index.php'></div>
</body>
</html>
the template,
<div id='content' ng-app='MyTutorialApp' ng-controller='MainController'>
<input type='text' ng-model='searchText' />
<ul>
<li ng-repeat='person in people | filter:searchText' ng-show='person.live == true'>#{{person.id}} {{person.name}}</li>
</ul>
<input type='text' ng-model='newPerson' />
<button ng-click='addNew()'>Add</button>
</div>
js/app.js,
var app = angular.module('MyTutorialApp',[]);
js/maincontroller.js,
app.controller("MainController", function($scope){
$scope.people = [
{
id: 0,
name: 'Leon',
music: [
'Rock',
'Metal',
'Dubstep',
'Electro'
],
live: true
},
{
id: 1,
name: 'Chris',
music: [
'Indie',
'Drumstep',
'Dubstep',
'Electro'
],
live: true
}
];
$scope.newPerson = null;
$scope.addNew = function() {
if ($scope.newPerson != null && $scope.newPerson != "") {
$scope.people.push({
id: $scope.people.length,
name: $scope.newPerson,
live: true,
music: [
'Pop',
'RnB',
'Hip Hop'
]
});
}
}
});
EDIT:
Directories,
index.html
js/
...
...
template/
index.php
EDIT 2:
index.html,
<div ng-app='MyTutorialApp'>
<div ng-include='template/index.php'></div>
</div>
template/index.php,
<div id='content' ng-controller='MainController'>
<input type='text' ng-model='searchText' />
<ul>
<li ng-repeat='person in people | filter:searchText' ng-show='person.live == true'>#{{person.id}} {{person.name}}</li>
</ul>
<input type='text' ng-model='newPerson' />
<button ng-click='addNew()'>Add</button>
</div>
Live demo here (click).
ng-include looks for a $scope property, so you need to pass it a string, like this: ng-include="'/template/index.php'".
<div ng-include="'/template/index.php'"></div>
What you were passing to it essentially makes it look for this in your controller: $scope['/template/index.php'] = 'some string';
You're also bootstrapping angular in the template itself - so how could it be included? ng-app needs to be in the main page so that ng-include can work!
<some-element ng-app="myApp">
<!-- in here, angular things work (assuming you have created an app called "myApp" -->
<div ng-include="'/template/index.php'"></div>
</some-element>
Just replace some-element with something like html, body or whatever element you want the app to work from.
You bootstrapped your ng-app in the template, but you have to bootstrap it in your main page.
So just move the ng-app directive from the template to the main-page, e.G.
<html ng-app="MyTutorialApp">
<div ng-include src='template/index.php'></div>
try this
and add ng-app into top of the page
<html ng-app='MyTutorialApp'>
you must have bootstrap you angular application into your index.html

Categories

Resources