AngularJS "Controller as" in templates - javascript

I am new to AngularJS world and I am trying to setup a basic laravel/angular JWT auth following this tutorial.
What I'd like to do, it's to use the "Controller As" syntax instead of the $scope as stated in the tutorial. For now, here what I have:
app.js
var app = angular.module('app', ['ngRoute']);
app.run(function () {});
app.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl: 'js/templates/login.html',
controller: 'LoginController'
});
});
login controller
angular.module('app')
.controller('LoginController', function ($scope) {
this.title='toto';
this.data = {};
this.submit = function () {
console.log(this.data);
};
});
admin view
<!doctype html>
<html lang="en">
<head>
<title>Blog Administration</title>
<!--css-->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"/>
<!--js-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<!--angular-->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers/loginController.js"></script>
</head>
<body ng-app="app">
<div id="wrapper">
<div class="container" id="view" ng-view>
</div>
</div>
</body>
</html>
login template
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body ng-controller="LoginController as login">
<div class="container">
<div id="login" class="col-md-4 col-md-offset-4">
<div id="login-form">
<h4>{{ login.title }}</h4>
<form ng-submit="login.submit()"><!--username-->
<div class="form-group">
<input id="username" type="text" ng-model="login.data.username"/>
</div>
<!--password-->
<div class="form-group">
<input id="password" type="password" ng-model="login.data.password"/>
</div>
<!--submit-->
<div class="form-group">
<button class="btn btn-primary" type="submit">Login</button>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
The problem is that nothing renders. Is it possible to use a controller per template ?
If I put the <ng-controller="LoginController as login"> directive in the view body instead of template everything renders correctly.
Is it a good practice to define a controller per template ? Because the login template should be as generic as possible, so it can be loaded in any view if the user isn't authenticated, that's why I think putting login() action in the controlelr handling the Admin view is wrong.
Can someone advice me on the best practices to have here ?

In order to use controllerAs syntax with routeProvider you need to declare additional property in route configuration:
$routeProvider.when('/', {
templateUrl: 'js/templates/login.html',
controller: 'LoginController',
controllerAs: 'login'
});
Then you need to clean up login template, removing everything but actual template, e.g. no HTML, body tags, etc. You also don't need extra ngController directive in partial template:
<div id="login" class="col-md-4 col-md-offset-4">
<div id="login-form">
<h4>{{ login.title }}</h4>
<form ng-submit="login.submit()">
<!--username-->
<div class="form-group">
<input id="username" type="text" ng-model="login.data.username" />
</div>
<!--password-->
<div class="form-group">
<input id="password" type="password" ng-model="login.data.password" />
</div>
<!--submit-->
<div class="form-group">
<button class="btn btn-primary" type="submit">Login</button>
</div>
</form>
</div>
</div>

Question 1: Is it possible to use a controller per template ?
Ans: Yes. Its very simply. How, is shown in next answer.
Question 2: Is it a good practice to define a controller per template ?
Ans: As per the AngularJs shown rules, Its good practice. Now see the 2
different way of defining the controller for the template.
a. Directly into the template like: <div ng-controller="myCtrl">Whole template
data goes inside this div.</div>
b. from the app.js where we load the template like this:
.state('app.products.all', {
url: '/all',
templateUrl: 'tpl/products/blocks/thumb.html',
controller: 'ProductsAllCtrl'
})
Here i have also shown the controller with the template path. Second way is
more better then the first.

Related

Angular Submit Syntax and message if no results found using MovieDB API

I'm super new at web development and am trying to learn how to use Angular for a mini project. I'm using The MovieDB's restful API's and all I want to do is a simple search for a movie title, return results that are found, and return a message if nothing is found.
Unfortunately I'm hitting a few comprehension hurdles and I have looked for a solution but haven't found one that matches what I'm doing, which I think is pretty simple (most of the ones I've seen are for more complex approaches and I think it's just beyond my understanding for the moment)
All I want to do right now is have a searchbar, a user types in a movie name, clicks submit, and the angular app will return results. But I can't quite figure out how to pass the submit through to my app. Here is my html code:
<!doctype html>
<html>
<head>
<link
href="http://s3.amazonaws.com/codecademy-content/projects/bootstrap.min.css"
rel="stylesheet" />
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js">
</script>
<!-- Modules -->
<script src="js/app.js"></script>
<!-- Controllers -->
<script src="js/controllers/MainController.js"></script>
<link href="css/main.css" rel="stylesheet" />
</head>
<body ng-app="myApp">
<div class="header">
<img src="img\logo.png"
style="width: 80px; height: 80px;>
<div class="container">
<h1>The MovieDB Search Tool</h1>
<h2>Search for a movie!</h2>
</div>
<div class="main" ng-controller='MainController'>
<div class="searchbar">
<form ng-submit="submitFunction(field)">
<input type="text" name="field" placeholder="Search for a
movie">
<input type="submit" value="Submit">
</form>
</div>
<div class="container">
<div ng-repeat="details in movieList" class="col-md-6">
<div class="thumbnail">
<img ng-
src="https://image.tmdb.org/t/p/w154{{details.poster_path}}">
<p>{{ details.title }}</p>
<p class="date">Release Date: {{ details.release_date | date
}}</p>
<p>{{details.overview}}</p>
</div>
</div>
</div>
</div>
<div class="footer">
<div class="container"></div>
</div>
</body>
</html>
And my javascript code for the angular app:
app.controller('MainController', ['$scope', '$http', function($scope, $http) {
$scope.movieTitle = function submitFunction(field){
}
$http.get('https://api.themoviedb.org/3/search/movie?api_key='+api_key+'&language=en-US&query='
+$scope.movieTitle+'&page=1&include_adult=false')
.then(successCallback, errorCallback);
function successCallback(response){
$scope.movieList = response.data.results
}
function errorCallback(error){
}
}]);
If I plug in a movie name like 'Deadpool' the html works just fine, of course with a static value it runs automatically. And I need it to work on submit, and the way I'm trying isn't working. I would think I need to get a variable passed in to the $scope, buy the submit function but I'm not getting anything when I run this.
If I could get to this point, I think I could figure out the logic to display a message of no results found, it should be as simple as checking the json object the api returns and looking at the "total results" number, then returning a specific message (at least I hope it's that simple).
Any and all help is appreciated!
HTML:
<form ng-submit="submitFunction()">
<input type="text" ng-model="movieTitle" placeholder="Search for a
movie">
<input type="submit" value="Submit">
</form>
CONTROLLER:
app.controller('MainController', ['$scope', '$http', function($scope, $http) {
$scope.submitFunction = function(){
$http.get('https://api.themoviedb.org/3/search/movie?api_key='+api_key+'&language=en-US&query='+$scope.movieTitle+'&page=1&include_adult=false')
.then(successCallback, errorCallback);
}
function successCallback(response){
$scope.movieList = response.data.results
}
function errorCallback(error){
}
}]);

Angular ui-router doesn't work

I'm new to Angular, i've been trying to use ui-router in this project, but ui-view doesn't show anything, did i miss something?.
I'm trying to build a mean app, the folder structure is the following:
The app folder is where the angular app is located.
<!DOCTYPE html>
<html lang="en" ng-app="TimeWaste">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" >
</head>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="">
<input type="text" ng-model="login.email">
<input type="password" ng-model="login.password">
<button>Login</button>
<a ui-sref="signUp">Create an account</a>
</div>
</div>
</nav>
<body>
<div ui-view></div>
</body>
<script src="node_modules/angular/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<script src="app/app.js"></script>
<script src="app/signup/signup-controller.js"></script>
</html>
this is the app.js
(function()
{
angular.module('TimeWaste',['ui.router'])
.config(function($stateProvider)
{
$stateProvider
.state('signup',{
url:"/signup",
templateUrl: "app/signup/signup.html",
controller:"SignupController"
})
})
}());
the signup.html view
<div class="row">
<div class="col-sm-6">
<div class="row">
<strong>Email Address:</strong>
<input type="text" ng-model="newUser.email" class="form-control">
</div>
<div class="row">
<strong>Password:</strong>
<input type="password" ng-model="newUser.password" class="form-control">
</div>
<button ng-click="createUser()">Submit</button>
</div>
</div>
and the signup controller
(function()
{
angular.module('TimeWaste')
.controller('SignupController', ['$scope','$state',function($scope,$state){
}]);
}());
It may typo and path missing !!
in html used <a ui-sref="signUp">Create an account</a> but in $stateProvider used signup so need to change signUp to signup.
and I assume your app.js is in app directory because you use
<script src="app/app.js"></script> in home page.
if right then your template path need to change templateUrl: "signup/signup.html",
However you can configure ui.route to be case insensitive.
like:
.config(function($stateProvider,$urlMatcherFactoryProvider,)
{
$urlMatcherFactoryProvider.caseInsensitive(true);
$urlMatcherFactoryProvider.strictMode(false);
$stateProvider
.state('signup',{
url:"/signup",
templateUrl: "signup/signup.html",
controller:"SignupController"
})
})

Angularjs - Controller call init() function multiple times

I have a problem while I'm making an angularjs app.
I create a controller and bind it in routeProvider. With a function to initialize values for the controller like this.
angular.module('app.Login', ['app.rpc','ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: '/static/tour/app/login/login.html',
controller: 'loginController'
});
}])
.controller('loginController', function($scope, $location, rpc) {
$scope.init = function() {
$scope.error = "";
console.log("Login Initialized");
}
$scope.init();
});
for login.html like this
<div class="container">
<div class="row">
<div class="col-xs-12">
<h1 class="page-header">Login</h1>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="alert alert-danger alert-dismissable" role="alert" ng-show="error">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<strong>Error: </strong>
<span>{{error}}</span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<form>
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" ng-model="username" placeholder="Username">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" ng-model="password" placeholder="Password">
</div>
<button class="btn btn-primary action-btn" ng-click="login()">Login</button>
</form>
</div>
</div>
</div>
When I run the app, it call init() 3 times like this.
login
Find out in this stackoverflow that many people also get this troble. All of them solved by make sure that controller doesn't bind more than one time (in routProvider and in template), and check that only one ng-app in the template.
My main html like this.
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="UTF-8">
<title>Touring</title>
<!--Bootstrap-->
<link rel="stylesheet" href="/static/tour/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/tour/css/bootstrap-theme.min.css">
<!--/Bootstrap-->
</head>
<body>
<ng-view><ng-view>
<!--Angular-->
<script src="/static/tour/js/angular.min.js"></script>
<script src="/static/tour/js/angular-route.min.js"></script>
<script src="/static/tour/js/angular-cookies.min.js"></script>
<!--/Angular-->
<!--App-->
<script src="/static/tour/app/app.js"></script>
<script src="/static/tour/app/rpc/app-rpc.js"></script>
<script src="/static/tour/app/login/app-login.js"></script>
<script src="/static/tour/app/dashboard/app-dashboard.js"></script>
<script src="/static/tour/app/memo/app-memo.js"></script>
</body>
</html>
For my main app like this.
angular.module('app',
['ngCookies',
'ngRoute',
'app.Login',
'app.Dashboard',
'app.Memo',
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
resolve: {
"check": function($cookies, $location) {
if(!$cookies.get("user_id")) {
$location.path("/login");
}
else {
$location.path("/dashboard");
}
}
}
})
.when('/logout', {
resolve: {
"check": function($cookies, $location) {
if($cookies.get("user_id")){
alert("You have been Logout");
}
$cookies.remove("user_name");
$cookies.remove("user_id");
$cookies.remove("token");
$cookies.remove("dbname");
$location.path("/login");
}
}
});
}]);
It ok for this controller, I just want to initialize a text but it's not ok for init in some controller that need some AJAX request to server side, could make too many request for noting. Anyone can solve this please help me. Thanks.
PS1. My practice base on angular-seed https://github.com/angular/angular-seed
PS2. At first, I also used jquery and it show WARNING: Tried to load angular more than once. Once I remove jquery it never show warning again, but it didn't fix my problem
I already solve it
<ng-view><ng-view>
use this instead
<div ng-view></div>
Concerning your multiple method call, are you sure your current URL is exactly the same as defined in the $routeProvider config? (maybe ngRoute redirects from /login/ to /login and calls your controller twice)
PS2. At first, I also used jquery and it show WARNING: Tried to load angular more than once. Once I remove jquery it never show warning again, but it didn't fix my problem
AngularJS already contains a lite version of jQuery: jqLite. If jQuery is loaded before Angular, this last one will use it. If not, it use the built-in lite version.
In your case, the error is probably due to a jQuery loading after the Angular loading. Angular already loads its version and you load it again.
Try to load jQuery before Angular or do not load it at all.

Assigning controller to a form template with $routeProvider in AngularJS

I'm building my first angular app, starting with a simple login form. I load the form from a partial, however when I try submitting the form, nothing is logged to the console, i.e. I assume my authenticate() method is not called. I have the following definition for my app.js:
'use strict';
angular.module('spForums',[])
.config(['$routeProvider','$locationProvider',function($routeProvider,$locationProvider) {
$routeProvider.when('/login', {
templateUrl: 'static/partials/login.html',
controller: loginController,
controllerAs: 'login'
});
$locationProvider.html5Mode(true);
}])
And here's the controller, defined in a separate controller.js:
'use strict';
function loginController() {
this.email = '';
this.password = '';
this.authenticate = function () {
console.log(this.email);
console.log(this.password);
};
};
Here's the partial, login.html:
<form class="form-signin" novalidate ng-submit="login.authenticate()">
<h2 class="form-signin-heading">Please sign in</h2>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus ng-model="login.email">
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" ng-model="login.password" id="inputPassword" class="form-control" placeholder="Password" required>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<input class="btn btn-primary" type="submit" value="Sign-in">
</form>
And here's the relevant part of index.html, or in my case, forum.html that includes the partial:
<!doctype html>
<html lang="en" ng-app="spForums">
<head>
<script type="text/javascript" src="/static/js/lib/angular.min.js"></script>
<script type="text/javascript" src="/static/js/lib/angular-resource.min.js"></script>
</head>
<body>
<div class="container" id="forumcontainer" ng-view>
</div> <!-- /container -->
<script type="text/javascript" src="/static/js/app.js"></script>
<script type="text/javascript" src="/static/js/controller.js"></script>
</body>
</html>
I'd like to end this by saying I'm new to Angular-JS. As in I just saw a bunch of tutorials and this is my first app. Please tell me where I'm wrong.
EDIT:- I'm using Angular-JS version 1.0.7.
You need to include ngRoute module into your application, it's not shipped by default:
<head>
<script>document.write('<base href="' + document.location + '" />');</script>
<script src="/static/js/lib/angular.min.js"></script>
<script src="/static/js/lib/angular-route.min.js"></script>
<script src="/static/js/lib/angular-resource.min.js"></script>
</head>
Note, that you also need to define base href tag, since you are using HTML5 mode.
Then define module with necessary dependencies:
angular.module('spForums', ['ngRoute', 'ngResource'])

Angular controller not working

I'm newbie to angular
My angular controller is:
var chatApp = angular.module('chatApp.controllers', []);
chatApp.controller('loginController', ['$scope', function($scope) {
$scope.user_name="name";
$scope.user_password="name";
}]);
the app.js is:
'use strict';
angular.module('chatApp', [
'ui.router',
'chatApp.filters',
'chatApp.services',
'chatApp.directives',
'chatApp.controllers'
]).config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('login', {
url: "/login",
templateUrl: "partials/login.html",
controller : "loginController"
})
});
login.html is:
<div>
<div id="wrapper">
<form name="login-form" class="login-form" action="" method="post">
<div class="header">
<h1>Login Form</h1>
</div>
<div class="content">
<input name="username" type="text" class="input username" placeholder="{{user_name}}" />
<div class="user-icon"></div>
<input name="password" type="password" class="input password" placeholder="{{user_password}}" />
<div class="pass-icon"></div>
</div>
</form>
</div>
I've used stateprovider for routing.
But, it's not showing anything in placeholder. What is the reason?
Solved the problem using ng-model instead of {{}}.
<div class="content">
<input name="username" type="text" class="input username" placeholder="username" ng-model="user_name" />
<div class="user-icon"></div>
<input name="password" type="password" class="input password" placeholder="password" ng-model="user_password"/>
<div class="pass-icon"></div>
</div>
This works for me if I say ng-controller = "loginController" in the html-
<div ng-controller = 'loginController'>
<div id="wrapper">
<form name="login-form" class="login-form" action="" method="post">
<div class="header">
<h1>Login Form</h1>
</div>
<div class="content">
<input name="username" type="text" class="input username" placeholder="{{user_name}}" />
<div class="user-icon"></div>
<input name="password" type="password" class="input password" placeholder="{{user_password}}" />
<div class="pass-icon"></div>
</div>
</div>
Here's a JSBin with it working: http://jsbin.com/aDuJIku/265/edit?html,js,output
This solution doesn't include ui-router, but it should work with it.
Try this:
var chatApp = angular.module('chatApp.controllers', []);
chatApp.controller('loginController', ['$scope','$timeout', function($scope,$timeout) {
$timeout(function(){
$scope.user_name="name";
$scope.user_password="name";
},100);
}]);
you just have to change to RouteProvider, In your case you just do:
angular.module('chatApp', [ 'ngRoute' 'ui.router','chatApp.filters','chatApp.services', 'chatApp.directives', 'chatApp.controllers'])
.config(function($routeProvider) {
$routeProvider.when('/login', { templateUrl: "partials/login.html", controller: "loginController" })
});
please make sure that you have angular-route js included.
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular-route.js"></script>
Hope this help you! ;)
Here's some examples for you this
Below mentioned code works.
Note: If somebody tries to run this code in preview its not going to work. JS and HTML code needs to be copied in separate file and use the names mentioned.
var myContrlApp = angular.module('ContrlApp', []);
myContrlApp.controller('MainController', function ($scope) {
var person = {
firstName: "Keith",
lastName: "Jackson",
};
$scope.message = "Welcome, Angular !";
$scope.person = person;
});
<html ng-app="ContrlApp">
<head>
<script type="text/javascript" src="Scripts/angular.js"></script>
<script type="text/javascript" src="Scripts/angular-route.js"></script>
<script type="text/javascript" src="Scripts/script.js"></script>
<!--<link rel="stylesheet" href="style.css" />-->
<title>Angular JS Tryout</title>
</head>
<body ng-controller="MainController">
<div>
<h1>{{message}}</h1>
<div>
<div>First name: {{person.firstName}}</div>
<div>Last name: {{person.lastName}}</div>
</div>
</div>
</body>
</html>

Categories

Resources