I'm trying to pass localStorage to input field, but i'm not able to pass the values, i not getting where i'm going wrong, please help me with this, 1 thing more how can i call the angularjs function outside the controller. thanx for any help guys.
html
<div class="modal__content" ng-controller="joinctrl">
<form novalidate>
<input type="email" placeholder="Email" ng-model="email"><br />
<input type="password" placeholder="Password" ng-model="password"><br />
<input type="password" placeholder="Confirm Password" ng-model="cpassword"><br />
<input type="submit" value="Create" class="creat" ng-click="create()">
</form>
</div>
js
preauth();
function preauth() {
var user_login = window.localStorage.getItem('email');
var pass_login = window.localStorage.getItem('password');
if(user_login != undefined && pass_login != undefined) {
alert(user_login);
document.getElementById("email").value=user_login;
document.getElementById("password").value=pass_login;
angular.element(document.getElementById('loginctrl')).scope().Login();
}
}
var app = angular.module('contol', ['onsen']);
app.controller('loginctrl', function($scope, $http){
$scope.login=function(){
if (!$scope.email || !$scope.password){
alert("Please Fill Email & Password");
}
else{
var request=$http({
method:"post",
url:"http://www.example.com/login.php",
dataType: "json",
data:{
email:$scope.email,
password:$scope.password
},
headers:{'Content-Type':'application/x-www-form-urlencoded'}
});
request.success(function(retmsg){
if(parseInt(retmsg.status)==0)
{
alert(retmsg.txt);
}
else if (parseInt(retmsg.status)==1)
{
window.localStorage.setItem('email', $scope.email);
window.localStorage.setItem('password', $scope.password);
myNavigator.pushPage('home.html');
}
});
}
};
});
This may be useful,store it in variable and use it and only id name not #password
var x = document.getElementById("password").value = "Password";
alert ("The value was changed to: " + x);
In Angular applications, you should write ALL code inside modules. Otherwise, you don't use one of the useful feature of Angular: modularity.
For example:
app.factory("LocalStorage", function() {
var LS = {};
LS.getItem = function(key) {
return localStorage[key];
};
LS.setItem = function(key, value) {
localStorage[key] = value;
return value;
};
return LS;
});
app.controller('loginctrl', function($scope, $http, LocalStorage) {
$scope.email = LocalStorage.getItem('email');
$scope.password = LocalStorage.getItem('password');
$scope.login = function() {
// code...
// I'd rather to create another service "Api" or "Request", like this:
return Api.doAuth($scope.login, $scope.password).then(function(res) {
// For example, service `Request` write to `LocalStorage` status of current authentication.
if(res) {
myNavigator.pushPage('home.html');
}
});
};
});
You should not to call function in outside application (it's incorrect from the point of view Angular's philosophy). However, it's possible, you wrote right:
// get our scope:
var scope = angular.element(document.getElementById('loginctrl')).scope();
// and call our function in the scope:
scope.login();
But it's code you need to execute after Angular's bootstrap.
Also, you may to execute any function with Angular's services.
//find the `ng:app` element and get injector.
var injector = angular.element('body').injector();
//execute our own function with any services
injector.invoke(function($rootScope, $http, LocalStorage) {
$http.get('/foo.php').then(function(res) {
LocalStorage.setItem('answer', res);
});
$rootScope.bar = 1;
});
Related
I am using a custom directive to submit a form programmatically however no form validation is applied before submitting the form. I have called $setDirty() on the form field and $setSubmitted() on the form but the form is still submitted even if the required form field is empty.
directives/external.submit.js
export default class externalSubmit {
constructor ($timeout) {
'ngInject';
this.$timeout = $timeout;
this.restrict = 'A';
this.scope = {};
}
link($scope, $element, $attrs) {
$scope.$on('submit-form', function(event, data){
if( data.id === $attrs.id ) {
setTimeout(function() {
/**
* set form and fields to dirty
* this should be enabling validation
**/
var $formScope = angular.element($element).scope();
var $formController = $formScope[formName];
$formController.$setDirty();
$formController.$setSubmitted();
angular.forEach($formController.$error.required, function(field) {
field.$setDirty();
});
// trigger form submit
$element.triggerHandler('submit');
}, 0);
}
});
}
// Create an instance so that we can access this inside link
static factory() {
externalSubmit.instance = new externalSubmit();
return externalSubmit.instance;
}
};
foo/foo.controller.js
export default class FooController {
constructor( $rootScope ) {
'ngInject';
this.$rootScope = $rootScope;
this.item = {};
}
save() {
alert('Save triggered');
}
submitForm(id) {
// if no form id given, use the first form in the content area
if ( ! id ) id = $('form')[0].id;
this.$rootScope.$broadcast('submit-form',{'id':id} );
}
}
foo/foo.html
<form external-submit id="primary" ng-submit="$ctrl.save()" go-back="dashboard.home()">
<input type="hidden" ng-model="$ctrl.item.id"/>
<input required name="title" ng-model="$ctrl.item.title" type="text" />
<button type="submit">Internal Submit</button>
</form>
<button type="submit" ng-click="$ctrl.submitForm()">External Submit</button>
Use ng-submit="$valid && $ctrl.save()"
The solution is to check $formController to see if the form is valid before triggering the submit handler.
link($scope, $element, $attrs, $ctrl ) {
$scope.$on('submit-form', function(event, data){
if( data.id === $attrs.id ) {
let formName = $attrs.name;
setTimeout(function() {
// get the element scope
var $formScope = angular.element($element).scope();
// get the form controller using the form name
var $formController = $formScope[formName];
$formController.$setSubmitted();
// check if form is valid before triggering submit
if ( $formController.$valid ) {
$element.triggerHandler('submit');
}
// required to update form styles
$scope.$apply();
}, 0);
}
});
}
I got a requirement to bind a value to a particular model when the value in the other model contains a string starting with "https".
For example, I have two text fields both fields having different model
<input type="text" ng-model="modelText1">
<input type="text" ng-model="modelText2">
Suppose I type a value on the first text field "https", the first input model modelText1 have to bind to the second input model modelText2 and later on i have to maintain it as like two-way binding. i.e. the second field will automatically get the value dynamically when it contains "https" at starting of a string.
Try it like in this Demo fiddle.
View
<div ng-controller="MyCtrl">
<input type="text" ng-model="modelText1">
<input type="text" ng-model="modelText2">
</div>
AngularJS Application
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.modelText1 = '';
$scope.modelText2 = '';
var regEx = new RegExp(/^https/);
$scope.$watch('modelText1', function (newValue) {
if (newValue.toLowerCase().match(regEx)) {
$scope.modelText2 = newValue;
} else {
$scope.modelText2 = '';
}
});
});
An other approach is (that avoid using of $watch) is to use AngularJS ng-change like in this
example fiddle.
View
<div ng-controller="MyCtrl">
<input type="text" ng-model="modelText1" ng-change="change()">
<input type="text" ng-model="modelText2">
</div>
AngularJS Application
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.modelText1 = '';
$scope.modelText2 = '';
var regEx = new RegExp(/^https/);
$scope.change = function () {
if ($scope.modelText1.toLowerCase().match(regEx)) {
$scope.modelText2 = $scope.modelText1;
} else {
$scope.modelText2 = '';
}
};
});
You can use the ng-change directive like this:
<input type="text" ng-model="modelText1" ng-change="onChange()">
<input type="text" ng-model="modelText2">
and your controller:
$scope.onChange = function() {
if ($scope.modelText1 === 'https') {
$scope.modelText2 = $scope.modelText1;
else
$scope.modelText2 = '';
};
use ng-change to check the text is equal to 'https'
angular.module('app',[])
.controller('ctrl',function($scope){
$scope.changeItem = function(item){
$scope.modelText2 = "";
if(item.toLowerCase() === "https"){
$scope.modelText2 = item
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<input type="text" ng-model="modelText1" ng-change="changeItem(modelText1)">
<input type="text" ng-model="modelText2">
</div>
EDiTED
to make sure it does't fail under 'HTTPS' use toLoweCase function to make all lower case
HTML :
<input type="text" ng-model="modelText1" ng-change="updateModal(modelText1)">
JS :
var modelText1 = $scope.modelText1.toLowerCase();
$scope.updateModal = function(){
$scope.modelText2 = '';
if(modelText1.indexOf('https')!=-1){
$scope.modelText2 = modelText1;
}
}
you could also possibly do this as a directive if you want to have a more reusable solution over multiple views http://jsfiddle.net/j5ga8vhk/7/
It also keeps the controller more clean, i always try to use the controller only for controlling complex business logic and business data
View
<div ng-controller="MyCtrl">
<input type="text" ng-model="modelText1" >
<input type="text" ng-model="modelText2" model-listener="modelText1" model-listener-value="https" >
</div>
Angular JS
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.modelText1 = '';
$scope.modelText2 = '';
});
myApp.directive('modelListener', [function() {
return {
restrict: 'A',
controller: ['$scope', function($scope) {
}],
link: function($scope, iElement, iAttrs, ctrl) {
$scope.$watch(iAttrs.modelListener, function() {
if($scope[iAttrs.modelListener] === iAttrs.modelListenerValue ) {
$scope[iAttrs.ngModel] = $scope[iAttrs.modelListener];
} else {
$scope[iAttrs.ngModel] = "";
}
}, true);
}
};
}]);
I know the title is kind of ambiguous but here is the issue: I have 2 input fields in a form that look like this:
<form name="modifyApp" class="form-signin" ng-submit="modify(val)">
<input type="text" class="form-control" ng-model="val.name" id="appName">
<input type="number" class="form-control" ng-model="val.number" id="number" min="0" max="65535">
<button type="submit">Submit</button>
</form>
When I load the page I populate those two with some values from inside the controller:
angular.module('myApp').controller('modifyAppController', ['$scope', function($scope) {
function setFields(appName, appNumber){
document.getElementById("appName").value = appName
document.getElementById("number").value = appNumber
}
$scope.modify= function(val){
console.log(val)
}
}])
The problem is when I press the Submit button. The values won't get registered unless I change them. For example, if I press the Submit button nothing gets printed, but if I change the number or the name, it gets printed.
In your controller you can simply initialize the val object like this:
angular.module('myApp', [])
.controller('modifyAppController', ['$scope', function($scope) {
$scope.val = {
name: '',
number: 0
};
function setFields(appName, appNumber) {
$scope.val.name = appName;
$scope.val.number = appNumber;
}
$scope.modify = function(val) {
console.log(val);
};
}]);
You need to rewrite your controller:
angular.module('myApp').controller('modifyAppController', ['$scope', function($scope) {
$scope.val = {
name = 'My app name',
number = '1'
};
function setFields(appName, appNumber){
$scope.val.name = appName;
$scope.val.number = appNumber;
}
$scope.modify= function(){
console.log($scope.val);
}
}])
You don't need to directly modify the DOM values in Angular. All your $scope variables are available in your template.
why not just have the following as the first line in your form
<form name="modifyApp" class="form-signin" ng-submit="modify()">
and then your controller can look like this
$scope.val = {
name: '',
number:0//some default values
}
$scope.modify= function(){
console.log($scope.val)
}
In below form I'm checking that an e-mail address is required :
http://jsfiddle.net/U3pVM/16994/
I want to extend the validation so that it check that the first two characters begin with 'DD' . It seems I need to add a custom directive but I'm unsure how to link the e-mail fields with the directive ?
fiddle code :
<form ng-app="myApp" ng-controller="validateCtrl"
name="myForm" novalidate>
<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
</span>
</p>
<p>
<input type="submit"
ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||
myForm.email.$dirty && myForm.email.$invalid">
</p>
</form>
var app = angular.module('myApp', []);
app.controller('validateCtrl', function($scope) {
});
app.directive("myValidator", function(){
// requires an isloated model
return {
// restrict to an attribute type.
restrict: 'A',
// element must have ng-model attribute.
require: 'ngModel',
link: function(scope, ele, attrs, ctrl){
// add a parser that will process each time the value is
// parsed into the model when the user updates it.
ctrl.$parsers.unshift(function(value) {
if(value){
// test and set the validity after update.
var valid = value.charAt(0) == 'D' && value.charAt(1) == 'D';
ctrl.$setValidity('invalidAiportCode', valid);
}
return valid ? value : undefined;
});
}
}
});
Here's how I would do it, using an authentication example:
The simple markup:
<input type="email" ng-model="existingUser.email">
<button ng-click="login(existingUser)">Login</button>
The controller:
auth.controller('AuthCtrl', '$scope', 'validation', function($scope, validation) {
$scope.existingUser = {
email: '',
password: ''
}
$scope.login = function() {
validation.validateSignin($scope.existingUser)
.catch(function(err) {
// The validation didn't go through,
// display the error to the user
$scope.status.message = err;
})
.then(function(res) {
// Validation passed
if (res === true) {
// Do something
}
});
}
}
The factory:
auth.factory('validation', ['$q', function($q) {
return {
validateSignin: function(existingUser) {
var q = $q.defer();
if (existingUser.email.substring(0,2) !== 'DD') {
q.reject('The email must start with "DD"');
}
q.resolve(true);
return q.promise;
}
}
}]);
Let me explain what's happening, first I'm creating a factory which will carry out the validation. Then I'm creating a promise with a resolve and a reject method, the reject method will be called if the validation failed, and if it succeeded then the resolve will be called. Then in your controller you can do things based on the outcome.
Let me know if anything is unclear.
I have a form that looks like this:
<form name="myForm" ng-submit="saveDeployment()">
<input type="hidden" value="{{item.CloneUrl}}" name="cloneurl" />
<input type="hidden" value="{{Username}}" name="username" />
<input type="radio" name="deploymenttype" ng-model="item.deploymentType" value="azure" checked="checked">Azure
<br />
<input type="radio" name="deploymenttype" ng-model="item.deploymentType" value="ftp">FTP
<div id="azure" ng-show="item.deploymentType=='azure'">
<label for="azurerepo">Azure Git Repo</label>
<input type="text" name="azurerepo" ng-model="item.azurerepo" ng-class="{error: myForm.azurerepo.$invalid}" ng-required="item.deploymentType=='azure'" />
</div>
<div id="ftp" ng-show="item.deploymentType=='ftp'">
<label for="ftpserver">FTP Server</label>
<input type="text" name="ftpserver" ng-model="item.ftpserver" ng-class="{error: myForm.ftpserver.$invalid}" ng-required="item.deploymentType=='ftp'" />
<label for="ftppath">FTP Path</label>
<input type="text" name="ftppath" ng-model="item.ftppath" ng-class="{error: myForm.ftppath.$invalid}" ng-required="item.deploymentType=='ftp'" />
<label for="ftpusername">FTP Username</label>
<input type="text" name="ftpusername" ng-model="item.ftpusername" ng-class="{error: myForm.ftpusername.$invalid}" ng-required="item.deploymentType=='ftp'"/>
<label for="ftppassword">FTP Password</label>
<input type="password" name="ftppassword" ng-model="item.ftppassword" ng-class="{error: myForm.ftppassword.$invalid}" ng-required="item.deploymentType=='ftp'"/>
</div>
<input type="submit" value="Save" ng-disabled="myForm.$invalid"/>
</form>
Its setup so that the required fields and Save button are all working once data is entered. However, part of my validation will be, "Is the user already registered?" where I will use the data entered to hit the server via POST using $http.
Should I put that logic in the saveDeployment() function or is there a better place to put it?
*UPDATE:*
I've implemented the below which is applied as an attribute on a element but it calls the server/database on every key press which I don't like:
app.directive('repoAvailable', function ($http, $timeout) { // available
return {
require: 'ngModel',
link: function (scope, elem, attr, ctrl) {
console.log(ctrl);
ctrl.$parsers.push(function (viewValue) {
// set it to true here, otherwise it will not
// clear out when previous validators fail.
ctrl.$setValidity('repoAvailable', true);
if (ctrl.$valid) {
// set it to false here, because if we need to check
// the validity of the email, it's invalid until the
// AJAX responds.
ctrl.$setValidity('checkingRepo', false);
// now do your thing, chicken wing.
if (viewValue !== "" && typeof viewValue !== "undefined") {
$http.post('http://localhost:12008/alreadyregistered',viewValue) //set to 'Test.json' for it to return true.
.success(function (data, status, headers, config) {
ctrl.$setValidity('repoAvailable', true);
ctrl.$setValidity('checkingRepo', true);
})
.error(function (data, status, headers, config) {
ctrl.$setValidity('repoAvailable', false);
ctrl.$setValidity('checkingRepo', true);
});
} else {
ctrl.$setValidity('repoAvailable', false);
ctrl.$setValidity('checkingRepo', true);
}
}
return viewValue;
});
}
};
});
You don't need to make $http request in directive, better place for it is controller.
You can specify method inside controller - $scope.saveDeployment = function () { // here you make and handle your error on request ... }; you'll save error to scope and then create a directive that will watch $scope.yourResponseObject and set validity based on it.
Also if you need something like request and error on input field blur instead, you need to create a simple directive with elem.bind('blur', ...) where you call $scope.saveDeployment with callback to handle validity.
Take a look on the examples, there might be something similar - https://github.com/angular/angular.js/wiki/JsFiddle-Examples
Validating a form input field using an asynchronous $http ajax call is a common need, but I haven't found any implementations that were complete, reusable, and easy to use so I tried my best to make one.
This functionality is especially useful for checking if a username, email, or other field/column is unique, but there are plenty of other use cases where a value must be validated with an ajax call (as in your example).
My solution has the following features:
Accepts a "check" function from the $scope that makes the $http call or any kind of validation (synchronous or asynchronous)
Accepts a "gate" function from the $scope that allows the check to be bypassed based on the value or ngModel state.
Debounces the "check" function's execution until the user has stopped typing
Ensure that only the latest $http call result is used (in case multiple are fired and return out of order).
Allows for state bindings so that the UI can respond appropriately and conveniently.
Customizable debounce time, check/gate functions, binding names and validation name.
My directive is pmkr-validate-custom (GitHub). It can be used for any asynchronous validation. I've tested it in several versions as far back as 1.1.5.
Here is a sample usage with Twitter Bootstrap in which I check if a username is unique.
Live Demo
<form name="the_form" class="form-group has-feedback">
<div ng-class="{'has-success':userNameUnique.valid, 'has-warning':userNameUnique.invalid}">
<label for="user_name">Username</label>
<input
name="user_name"
ng-model="user.userName"
pmkr-validate-custom="{name:'unique', fn:checkUserNameUnique, gate:gateUserNameUnique, wait:500, props:'userNameUnique'}"
pmkr-pristine-original=""
class="form-control"
>
<span ng-show="userNameUnique.valid" class="glyphicon glyphicon-ok form-control-feedback"></span>
<span ng-show="userNameUnique.invalid" class="glyphicon glyphicon-warning-sign form-control-feedback"></span>
<i ng-show="userNameUnique.pending" class="glyphicon glyphicon-refresh fa-spin form-control-feedback"></i>
<p ng-show="userNameUnique.valid" class="alert alert-success">"{{userNameUnique.checkedValue}}" is availiable.</p>
<p ng-show="userNameUnique.invalid" class="alert alert-warning">"{{userNameUnique.checkedValue}}" is not availiable.</p>
<button
ng-disabled="the_form.$invalid || the_form.user_name.$pristine || userNameUnique.pending"
class="btn btn-default"
>Submit</button>
</div>
</form>
Sample controller:
// Note that this ought to be in a service and referenced to $scope. This is just for demonstration.
$scope.checkUserNameUnique = function(value) {
return $http.get(validationUrl+value).then(function(resp) {
// use resp to determine if value valid
return isValid; // true or false
});
}
// The directive is gated off when this function returns true.
$scope.gateUserNameUnique = function(value, $ngModel) {
return !value || $ngModel.$pristine;
};
If I make any improvements, they will be up-to-date on GitHub, but I am also going to put the code here for this directive and its dependencies (may not be updated). I welcome suggestions or issues though GitHub issues!
angular.module('pmkr.validateCustom', [
'pmkr.debounce'
])
.directive('pmkrValidateCustom', [
'$q',
'pmkr.debounce',
function($q, debounce) {
var directive = {
restrict: 'A',
require: 'ngModel',
// set priority so that other directives can change ngModel state ($pristine, etc) before gate function
priority: 1,
link: function($scope, $element, $attrs, $ngModel) {
var opts = $scope.$eval($attrs.pmkrValidateCustom);
// this reference is used as a convenience for $scope[opts.props]
var props = {
pending : false,
validating : false,
checkedValue : null,
valid : null,
invalid : null
};
// if opts.props is set, assign props to $scope
opts.props && ($scope[opts.props] = props);
// debounce validation function
var debouncedFn = debounce(validate, opts.wait);
var latestFn = debounce.latest(debouncedFn);
// initially valid
$ngModel.$setValidity(opts.name, true);
// track gated state
var gate;
$scope.$watch(function() {
return $ngModel.$viewValue;
}, valueChange);
// set model validity and props based on gated state
function setValidity(isValid) {
$ngModel.$setValidity(opts.name, isValid);
if (gate) {
props.valid = props.invalid = null;
} else {
props.valid = !(props.invalid = !isValid);
}
}
function validate(val) {
if (gate) { return; }
props.validating = true;
return opts.fn(val);
}
function valueChange(val) {
if (opts.gate && (gate = opts.gate(val, $ngModel))) {
props.pending = props.validating = false;
setValidity(true);
return;
}
props.pending = true;
props.valid = props.invalid = null;
latestFn(val).then(function(isValid) {
if (gate) { return; }
props.checkedValue = val;
setValidity(isValid);
props.pending = props.validating = false;
});
}
} // link
}; // directive
return directive;
}
])
;
angular.module('pmkr.debounce', [])
.factory('pmkr.debounce', [
'$timeout',
'$q',
function($timeout, $q) {
var service = function() {
return debounceFactory.apply(this, arguments);
};
service.immediate = function() {
return debounceImmediateFactory.apply(this, arguments);
};
service.latest = function() {
return debounceLatestFactory.apply(this, arguments);
};
function debounceFactory(fn, wait) {
var timeoutPromise;
function debounced() {
var deferred = $q.defer();
var context = this;
var args = arguments;
$timeout.cancel(timeoutPromise);
timeoutPromise = $timeout(function() {
deferred.resolve(fn.apply(context, args));
}, wait);
return deferred.promise;
}
return debounced;
}
function debounceImmediateFactory(fn, wait) {
var timeoutPromise;
function debounced() {
var deferred = $q.defer();
var context = this;
var args = arguments;
if (!timeoutPromise) {
deferred.resolve(fn.apply(context, args));
// return here?
}
$timeout.cancel(timeoutPromise);
timeoutPromise = $timeout(function() {
timeoutPromise = null;
}, wait);
return deferred.promise;
}
return debounced;
}
function debounceLatestFactory(fn) {
var latestArgs;
function debounced() {
var args = latestArgs = JSON.stringify(arguments);
var deferred = $q.defer();
fn.apply(this, arguments).then(function(res) {
if (latestArgs === args) {
deferred.resolve(res);
}
}, function(res) {
if (latestArgs === args) {
deferred.reject(res);
}
});
return deferred.promise;
}
return debounced;
}
return service;
}
])
;
angular.module('pmkr.pristineOriginal', [])
.directive('pmkrPristineOriginal', [
function() {
var directive = {
restrict : 'A',
require : 'ngModel',
link: function($scope, $element, $atts, $ngModel) {
var pristineVal = null;
$scope.$watch(function() {
return $ngModel.$viewValue;
}, function(val) {
// set pristineVal to newVal the first time this function runs
if (pristineVal === null) {
pristineVal = $ngModel.$isEmpty(val) ? '' : val.toString();
}
// newVal is the original value - set input to pristine state
if (pristineVal === val) {
$ngModel.$setPristine();
}
});
}
};
return directive;
}
])
;
My solution was taken from Kosmetika's idea.
I used the angular-ui project and set an onBlur callback that was on the controller which called the web service via $http.
This set a controller/model property to true or false.
I then had a <span> use ng-show to watch the controller/model property so when the web service returned it would show the user information