I have the following controller:
app.controller('SignUpController', ['$http','$sessionStorage','api', '$scope','$state', '$log', 'Session','clientSocket', function ($http, $sessionStorage, api, $scope,$state, $log, Session, clientSocket) {
var signupCtrl = this;
signupCtrl.getRandomPerson = function () {
var isGuy = Math.floor((Math.random() * 2));
if(isGuy == 1 || isGuy == 0){
var picture = Math.floor((Math.random()*9));
return 'img/guys/guy-'+picture+'.jpg';
}else{
var picture = Math.floor((Math.random()*10));
return 'img/guys/woman-'+picture+'.jpg';
}
}
}]);
With the following html:
<div class="container w-xxl w-auto-xs" ng-controller="SignUpController as signUpCtrl" ng-init="app.settings.container = false;">
<div class="m-b-lg">
<div class="bg-white p-md">
<div class="block m-t text-center m-b-xl">
<img src="{{signUpCtrl.getRandomPerson()}}" alt="Company Logo" class="img-circle" style="display: inline-block">
</div>
<form name="form" class="form-validation">
<div class="list-group list-group-sm">
<div class="list-group-item">
<input placeholder="Name" class="form-control no-border" ng-model="user.name" required>
</div>
<div class="list-group-item">
<input type="email" placeholder="Email" class="form-control no-border" ng-model="user.email" required>
</div>
<div class="list-group-item">
<input type="password" placeholder="Password" class="form-control no-border" ng-model="user.password" required>
</div>
</div>
<div class="checkbox m-b-md m-t-none">
<label class="i-checks">
<input type="checkbox" ng-model="agree" required><i></i> Agree the <a href>terms and policy</a>
</label>
</div>
<button type="submit" class="btn btn-lg btn-primary btn-block" ng-click="signup()" ng-disabled='form.$invalid'>Sign up</button>
<div class="line line-dashed"></div>
<p class="text-center"><small>Already have an account?</small></p>
<a ui-sref="access.signin" class="btn btn-lg btn-default btn-block">Sign in</a>
</form>
</div>
</div>
<div class="text-center" ng-include="'tpl/blocks/page_footer.html'">
{% include 'blocks/page_footer.html' %}
</div>
When i am loading this page the function getRandomPerson gets fired over 10 times. Sometimes so much that angular throws the following execption:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [[{"msg":"fn: expressionInputWatch","newVal":"img/guys/guy-2.jpg","oldVal":"img/guys/guy-1.jpg"}],[{"msg":"fn: expressionInputWatch","newVal":"img/guys/guy-6.jpg","oldVal":"img/guys/guy-2.jpg"}],[{"msg":"fn: expressionInputWatch","newVal":"img/guys/guy-1.jpg","oldVal":"img/guys/guy-6.jpg"}],[{"msg":"fn: expressionInputWatch","newVal":"img/guys/guy-4.jpg","oldVal":"img/guys/guy-1.jpg"}],[{"msg":"fn: expressionInputWatch","newVal":"img/guys/guy-8.jpg","oldVal":"img/guys/guy-4.jpg"}]]
http://errors.angularjs.org/1.3.14/$rootScope/infdig?p0=10&p1=%5B%5B%7B%22m…guys%2Fguy-8.jpg%22%2C%22oldVal%22%3A%22img%2Fguys%2Fguy-4.jpg%22%7D%5D%5D
at REGEX_STRING_REGEXP (angular.js:63)
at Scope.$get.Scope.$digest (angular.js:14281)
at Scope.$get.Scope.$apply (angular.js:14506)
at done (angular.js:9659)
at completeRequest (angular.js:9849)
at XMLHttpRequest.requestLoaded (angular.js:9790)
Can anyone tell me whats going on?
The issue is that many digests might run on a particular scope within the page...even just to render once
Because every digest is seeing a new value from your function, it forces another digest. Thus you are creating an infinte loop
Just assign a scope variable randomImage and get that value returned from function, instead of placing function in the html
And as pointed out use ng-src so that final src gets set with a proper value after it is compiled. Otherwise you will have strange invalid path requests made to server
// will only run once when controller initializes
signupCtrl.randomImage = getRandomPerson();
// no need to be on scope since using it privately
var getRandomPerson = function() {
var isGuy = Math.floor((Math.random() * 2));
if(isGuy == 1 || isGuy == 0){
var picture = Math.floor((Math.random()*9));
return 'img/guys/guy-'+picture+'.jpg';
}else{
var picture = Math.floor((Math.random()*10));
return 'img/guys/woman-'+picture+'.jpg';
}
}
HTML
<!-- No src so browser won't make request to invalid path -->
<img ng-src="{{signUpCtrl.randomImage }}">
You have a src binding to your function, if you intend to do this you should be using ng-src so it won't be compiled before it is ready to be consumed.
Related
I am using a diective in ng-repeat which when i click i pass date and time to the function showAppointmentForm but here the problem is when I click on first index of loop i get date and time displayed in modal box but when I click on second ,third and so on its values are coming as function parameters but not displayed.Is this something problem with using directives in for loop.Can anyone please suggest help.Thanks.
Using directive in template,
<div data-ng-repeat="doctor in doctors">
<appointment-timings data-ng-if="appointments" appointments="appointments" physician="doctor.npi" width="2"></appointment-timings>
</div>
My appointmnt directive,
$scope.showAppointmentForm = function(date,time) {
$scope.appointmentData = {};
$scope.appointmentData.physician = $scope.physician;
$scope.appointmentData.date = '';
$scope.appointmentData.time = '';
$scope.appointmentData.date = date.toString();
$scope.appointmentData.time = time;
$scope.submitted = false;
$timeout(function () {
$scope.$apply();
$('#appointments').modal('show');
},500);
}
My Directive html,(A modal box)
<div class="date-time">
<div class="col-md-6 col-xs-6">
<div class="input-group">
<span class="input-group-addon"><b>DATE</b></span>
<input type="text" class="form-control" ng-model="appointmentData.date" disabled>
</div><!-- /input-group -->
</div>
<div class="col-md-6 col-xs-6">
<div class="input-group">
<span class="input-group-addon"><b>TIME</b></span>
<input type="text" class="form-control" ng-model="appointmentData.time" disabled>
</div>
</div>
</div>
<div class="scheduled-hours" id="scheduled-scroll">
<ul>
<li data-ng-click="showAppointmentForm(date, time)" data-ng-repeat="time in times">{{time}}</li>
</ul>
</div>
How do I access the individual input names defined in a form inside my controller?
rates.rateName
rates.rateBitrate
rates.rateWidth
rates.rateHeight
This does not work: var url = {{ tmp + data.rateName }};
I need to extract one of the input values from the form and append it to the url
to be used with a $http POST. I need to put the rest of the inputs from the form (all together) into the POST as well as json blob.
<div ng-controller="RateCtrlAdd">
<rd-widget>
<rd-widget-header icon="fa-users" title="Rates">
</rd-widget-header>
</rd-widget>
<p></p>
<div class="row">
<div class="col-sm-6">
<form name="myForm" ng-submit="SendData()">
<input class="form-control input-lg" type="text"
placeholder="rate name"
name="rates.rateName"
ng-model="rates.rateName" required/>
<br>
<input class="form-control input-lg" type="text"
placeholder="rate bit rate"
name="rates.rateBitrate"
ng-model="rates.rateBitrate" required/>
<br>
<input class="form-control input-lg" type="text"
placeholder="rate width"
name="rates.rateWidth"
ng-model="rates.rateWidth" required/>
<br>
<input class="form-control input-lg" type="text"
placeholder="rate height"
name="rates.rateHeight"
ng-model="rates.rateHeight" required/>
</form>
</div>
</div>
<div class="row" style="margin-top: 12px;">
<div class="col-sm-6">
<button class="btn btn-success btn" value="Send" ng-click="SendData()">
Add
</button>
<a href="/rates" class="btn btn-danger btn">
Cancel
</a>
</div>
</div>
</div>
'use strict';
angular.module('RDash')
.controller('RateCtrlAdd', ['$scope', '$http', function($scope, $http) {
console.log('RateCtrlAdd - enter...');
$scope.SendData = function () {
var data = $scope.rates;
console.log('RateCtrlAdd - rates from input form: ', $scope.rates);
var tmp = 'http://10.10.15.145:8085/lms/outputstream/';
var url = {{ tmp + data.rateName }};
console.log('RateCtrlAdd - url: ', url);
}; // end function()
console.log('RateCtrlAdd - ...exit');
}]); // end controller()
You cant use binding expression i.e. {{}} in controller. Add it using simple javascript
Try this
var url = tmp + data.rateName;
I am trying to learn angular.js and I want to load a form html through angular-route with a template.
I think I set up everything correctly, but the html form won't load on the url that I set on config. And the other config url I set up for testing won't work either.
Here is the code
index.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/style.css">
</head>
<body ng-app="EventPlanner">
<div ng-view></div>
</body>
</html>
<script type="text/javascript" src="/bower_components/angular/angular.min.js"></script>
<script type="text/javascript" src="/bower_components/angular-route/angular-route.min.js"></script>
<script type="text/javascript" src="/js/angular/ng_config.js"></script>
<script type="text/javascript" src="/js/angular/ng_controller.js"></script>
ng_config.js
angular.module("EventPlanner", ["ngRoute"])
.config(["$routeProvider", function($routeProvider){
$routeProvider.when("/", {
templateUrl: "template/register.html"
})
.when("/make_plan", {
template: "<h1>make plans</h1>"
});
}]);
ng_controller.js
angular.module("EventPlanner", [])
.controller("registerControl", [function(){
var self = this;
self.submit = function(){
location.href = "#/make_plan";
};
}]);
register.html
<div class="main container">
<div class="row" ng-controller="registerControl as regi">
<form ng-submit="regi.submit()" name="regiForm" class="register col-xs-12">
<label class="col-xs-12" for="name">
<span class="col-xs-2">Name</span>
<input ng-model="regi.username" class="col-xs-5" type="text" id="name" name="name" required>
<span class="col-xs-5" ng-show="regiForm.name.$error.required">This feild is required</span>
</label>
<label class="col-xs-12" for="email">
<span class="col-xs-2">Email</span><input ng-model="regi.email" class="col-xs-5" type="email" id="email" name="email" required>
<span class="col-xs-5" ng-show="regiForm.email.$error.required">This feild is required</span>
</label>
<label class="col-xs-12" for="birthday">
<span class="col-xs-2">Birthday</span><input ng-model="regi.birthday" class="col-xs-5" type="date" id="birthday">
</label>
<label class="col-xs-12" for="password">
<span class="col-xs-2">Password</span>
<input ng-model="regi.password" class="col-xs-5" type="password" id="password" name="password"
ng-pattern="/^(?=.*[0-9])(?=.*[!##$%^&*])[a-zA-Z0-9!##$%^&*]{6,16}$/" ng-minlength="6" ng-maxlength="16" required>
</label>
<ul class="col-xs-7">
<li class="col-xs-12" ng-show="regiForm.password.$error.pattern">Must contain one lower & uppercase letter, and one non-alpha character (a number or a symbol.)</li>
<li class="col-xs-12" ng-show="regiForm.password.$error.minlength">Password Must be more than 5 characters</li>
<li class="col-xs-12" ng-show="regiForm.password.$error.maxlength">Password Must be less than 20 characters</li>
<li class="col-xs-12" ng-show="regiForm.name.$dirty && regiForm.name.$error.required">Please enter name
</li>
</ul>
<div class="col-xs-7 no-padding">
<button type="submit" ng-disabled="regiForm.$invalid" class="btn">Submit</button>
</div>
</form>
</div>
I have been looking at the code over and over for past few days, I cannot figure out what I did wrong.
Please help.
Thank you.
You have an error in your code.
ng_config.js
angular.module("EventPlanner", ["ngRoute"]) // correct!
.config(["$routeProvider", function($routeProvider){
$routeProvider.when("/", {
templateUrl: "template/register.html"
})
.when("/make_plan", {
template: "<h1>make plans</h1>"
});
}]);
The above is correct, you are defining a new module 'EventPlanner' and defining an array of dependencies.
ng_controller.js
angular.module("EventPlanner", []) // incorrect!!
.controller("registerControl", [function(){
var self = this;
self.submit = function(){
location.href = "#/make_plan";
};
}]);
The above is incorrect. You do not need to pass an empty array anymore as you have already created your module 'EventPlanner'.
What is actually happening above is you are redefining the module 'EventPlanner' and overwriting your previous declaration.
Change ng_controller.js to the following:
angular.module("EventPlanner") // fixed
.controller("registerControl", [function(){
var self = this;
self.submit = function(){
location.href = "#/make_plan";
};
}]);
Now, when ng_controller.js is parsed, it tells angular that it wishes to create a 'registerController' for a previously defined module called 'EventPlanner'. Hope that makes sense.
I am new to AngularJS. I stored the response data in the scope in my controller . But the values stored in scope not getting displayed in the html page.
guest-controller.js
var guestProfileApp = angular.module('guestProfileApp', ['guestProfileServices' ]);
guestProfileApp.controller( 'guestProfileController', [ '$scope', 'guestProfileService', GuestProfileController ]);
function GuestProfileController( $scope, guestProfileService)
{
$scope.getProfile = getProfile;
$scope.saveProfile = saveProfile;
console.log('guest profile controller called');
function getProfile( profileID ){
return guestProfileService.getProfile( profileID ).then( function( response ){
$scope.profileBizObj = response.data;
console.log($scope.profileBizObj);
window.location = "profile.html";
});
}
}
profile.html
<html lang="en" ng-app="guestProfileApp">
<body ng-controller="guestProfileController">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" placeholder="First Name" id="f_firstName" ng-model="profileBizObj.profileData.nameInfo.firstName">
<div class="input-group-addon"><span class="glyphicon glyphicon-user"></span></div>
</div>
</div>
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" placeholder="Last Name" id="f_lastName" ng-model="profileBizObj.profileData.nameInfo.lastName">
<div class="input-group-addon"><span class="glyphicon glyphicon-user"></span></div>
</div>
</div>
<div class="form-group">
<div class="input-group">
<input type="date" class="form-control" placeholder="Date of Birth" id="f_dob" ng-model="profileBizObj.profileData.nameInfo.birthDate">
<div class="input-group-addon"><span class="glyphicon glyphicon-gift"></span></div>
</div>
</div>
</body>
</html>
When I displayed the response data using
console.log($scope.profileBizObj);
The data is displaying correctly. But when I am moving to "profile.html" and trying to display the profileBizObj data using ng-model the values are not getting displayed.
Here is the output of console.log($scope.profileBizObj);
{"addressList":[],
"customerID":"MYCUST",
"emailList":[],
"formattedName":"JOHN PAWLIW, #388569330",
"phoneList":[],
"profileData":{"createdOn":"2015-11-24T14:05:58",
"customerID":"MYCUST",
"nameInfo":{"createdOn":"2015-11-24T14:05:58",
"firstName":"JOHN",
"lastName":"JOHN PAWLIW",
"mergedObjectState":2,
"middleName":"",
"nameInfoID":12642,
"nameTitle":"MR",
"profileID":7183,
"selectedLocale":"en_US",
"updatedOn":"2015-11-24T14:05:58"},
"profileID":7183,
"selectedLocale":"en_US",
"status":"ACTIVE",
"updatedOn":"2015-11-24T14:05:58"},
"profileID":7183,
}
Please help me as how to resolve this issue . Thank You
In order to display the $scope.profileBizObj in view.html. You can use ng-repeatto iterate through object properties.
<div ng-repeat="item in profileBizObj">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" placeholder="First Name" id="f_firstName" ng-model="item.profileData.nameInfo.firstName">
<div class="input-group-addon"><span class="glyphicon glyphicon-user"></span></div>
</div>
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" placeholder="Last Name" id="f_lastName" ng-model="item.profileData.nameInfo.lastName">
<div class="input-group-addon"><span class="glyphicon glyphicon-user"></span></div>
</div>
</div>
</div>
This is the fiddle link: https://jsfiddle.net/rrwfu834/2/
window.location = "profile.html"
loads a new page. The new page shares no information with the previous page. It's like hitting reload or typing a new url into the browser window.
Looking at your code, simply try removing that line to see if resolves your issue.
There are several ways to load a template within the current page - the easiest of which is probably ng-include.
You can also use routes or ui.router.
The issue is resolved by making following changes
profiletest.html
<body>
<div ng-app="guestProfileApp">
<div ng-controller="guestProfileController">
<button ng-click="getProfile(1546)">Show Profile</button>
<ng-include ng-if="showProfile" src="'profile1.html'"></ng-include>
</div>
</div>
</body>
guest-controller.js
function GuestProfileController( $scope, guestProfileService)
{
$scope.getProfile = getProfile;
$scope.saveProfile = saveProfile;
console.log('guest profile controller called');
function getProfile( profileID ){
return guestProfileService.getProfile( profileID ).then( function( response ){
$scope.showProfile = true;
$scope.profileBizObj = response.data;
});
}
}
I've followed this tutorial about AngularJS Multi-Step Form Using UI Router. The form works and I can save my data but now I'm having questions about how to validate each step in the form.
I have the following form with input fields:
Step 1
License Plate
Step 2
Name
Street
Zipcode
City
Email
Telephone
Step 3
Choose a date & time from a calendar
It looks somewhat like this:
I have a general base view like this:
<body ng-app="formApp">
<div id="top"></div>
<div class="container">
<!-- views will be injected here -->
<div ui-view></div>
</div>
</body>
In my app.js I have the following (not complete, left the non important things out):
// app.js
// create our angular app and inject ngAnimate and ui-router
// =============================================================================
angular.module('formApp', ['ngAnimate', 'ui.router', 'ui.calendar'])
// configuring our routes
// =============================================================================
.config(function($stateProvider, $urlRouterProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
$stateProvider
// route to show our basic form (/form)
.state('form', {
url: '/form',
templateUrl: 'views/form.html',
controller: 'formController'
})
// nested states
// each of these sections will have their own view
// url will be /form/interests
.state('form.license', {
url: '/license',
templateUrl: 'views/form-license.html'
})
// url will be nested (/form/profile)
.state('form.profile', {
url: '/profile',
templateUrl: 'views/form-profile.html'
})
// url will be /form/payment
.state('form.appointment', {
url: '/appointment',
templateUrl: 'views/form-appointment.html'
})
// url will be /form/success
.state('form.success', {
url: '/success',
templateUrl: 'views/form-success.html'
});
// catch all route
// send users to the form page
$urlRouterProvider.otherwise('/form/license');
})
// our controller for the form
// =============================================================================
.controller('formController', function($scope, $http, $compile, $location, uiCalendarConfig) {
$scope.formData = {};
$scope.formData.profile = {};
$scope.next = function(step){
if(step == 1)
{
}
else if(step == 2)
{
}
};
// function to process the form
$scope.processForm = function(isValid) {
};
});
My general form.html:
<!-- form.html -->
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<div id="form-container">
<form id="appointment-form" name="appointmentform" ng-submit="processForm(appointmentform.$valid)">
<!-- our nested state views will be injected here -->
<div id="form-views" ui-view></div>
</form>
</div>
</div>
</div>
The first step in my form is in form-license.html:
<!-- form-license.html -->
<label>Nummerplaat ingeven</label>
<div class="form-group">
<div class="col-xs-8 col-xs-offset-2">
<input required type="text" class="form-control" name="license" ng-model="formData.license">
</div>
</div>
<div class="form-group row">
<div class="col-xs-4 col-xs-offset-4">
<a ng-click="next(1)" ui-sref="form.profile" class="btn btn-next btn-block">
Volgende
</a>
</div>
</div>
But now I'm wondering how I can validate this when they click on next button ... . It's not working with the normal required attribute.
Can somebody help me with this?
UPDATE:
Now I have in my first step the following:
<div class="col-xs-4 col-xs-offset-4">
<a ng-click="next(1, processForm)" ui-sref="form.profile" ng-disabled="!licenseValidated" class="btn btn-next btn-block">
Volgende
</a>
</div>
In my controller:
var validateLicense = function (newVal) {
var validated = false;
// Run your custom validation checks
if(newVal)
{
validated = true;
}
return validated;
};
$scope.$watch('formData.license', function (newVal) {
$scope.licenseValidated = validateLicense(newVal);
});
Ok, that works. But in my second step I have multiple fields like this:
<div class="profile">
<div class="form-group">
<label class="col-sm-3 control-label" for="name">Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="name" ng-model="formData.profile.name">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="street">Street</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="street" ng-model="formData.profile.street">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="zipcode">Zipcode</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="zipcode" ng-model="formData.profile.zipcode">
</div>
</div>
<div class="form-group row">
<div class="col-xs-8 col-xs-offset-2">
<a ng-click="next(1)" ui-sref="form.license" class="btn btn-block btn-previous col-xs-3">
VORIGE
</a>
<a ng-click="next(2)" ui-sref="form.appointment" class="btn btn-block btn-next col-xs-3">
Volgende
</a>
</div>
</div>
</div>
Do I need to create for every one of them a $scope.watch? And do I need to add them to ng-disabled of my button?
You could simply disable the next button if any of the validation steps doesn't pass.
Something like:
// Inside your controller.
// Don't overload the scope.
// Only assign what will be needed through your HTML or other AngularJS Scopes
var validateLicense = function (newVal) {
// If you are only checking for content to be entered
return (newVal !== '' && newVal !== undefined);
};
var validateInfo = function (newVal) {
if (newVal.length > 0) {
// Check to make sure that all of them have content
for (var i = 0, l = newVal.length; i < l; i++) {
if (newVal[i] === undefined || newVal[i] === '') {
return false;
}
}
// We didn't find invalid data, let's move on
return true;
}
return false;
};
var validateDate = function (newVal) {
var validated = false;
// Run your custom validation checks
return validated;
}
// Initialize the disabled "Next" buttons
$scope.licenseValidated = false;
$scope.infoValidated = false;
// Watch a single item in a form, if filled in we will let them proceed
$scope.$watch('formData.license', function (newVal) {
$scope.licenseValidated = validateLicense(newVal);
});
// Watch a multiple items in a form, if ALL are filled in we will let them proceed
// Note that the order in this array is the order the newVal will be,
// So further validation for formData.number would be on newVal[1]
$scope.$watchGroup(['formData.name', 'formData.number', 'formData.address'], function (newVal) {
$scope.infoValidated = validateInfo(newVal);
});
form-license.html add the ng-disabled attribute on your next button:
<a ng-click="next(1, appointmentform)" ui-sref="form.profile" class="btn btn-next btn-block" ng-disabled="!licenseValidated">
Volgende
</a>
form-info.html repeat above steps
<a ng-click="next(1, appointmentform)" ui-sref="form.profile" class="btn btn-next btn-block" ng-disabled="!infoValidated">
Volgende
</a>
And so on...
See this Fiddle for Demo
You have a couple of options available to you depending on how you want to approach it.
To start, you should use ng-form for each of the 3 form steps. This will allow you to validate each individually without having to worry about the other sections.
So as an example your first form step might turn into:
<ng-form name="LicenseForm">
<label>Nummerplaat ingeven</label>
<div class="form-group">
<div class="col-xs-8 col-xs-offset-2">
<input required type="text" class="form-control" name="license" ng-model="formData.license">
</div>
</div>
<div class="form-group row">
<div class="col-xs-4 col-xs-offset-4">
<a ng-click="next(1, LicenseForm)" ui-sref="form.profile" class="btn btn-next btn-block">
Volgende
</a>
</div>
</div>
</ng-form>
This gives you access to the form validation properties for just this step. At this point you can update your controller to use .$invalid or .$valid on the form object that is now being passed in the next submit button, meaning you can now do something like:
$scope.next = function(step, form) {
if (form.$invalid) {
console.log('Form is invalid!');
return;
}
// move to next section
...
};