Validate directive elements from a form on the main page - javascript

My question is about handling client side validations for a large Angular app. I have a big SPA app with different components which includes reusable components like zip control. Now I can integrate these components in my page form but how can I trigger the validations for elements residing within the components. For e.g. my zip component has city input box, state select box and zip input box, now how can I trigger validations for these components from form submit?

I am using the following solution for my application for now. I am able to validate the required fields with this solution.
I created two input field one from the directive and other within the form. I am able to show error messages for both the fields. Similarly this can be done for some other form of validations.
Here is my plunker
https://plnkr.co/edit/laW9jYoNCszHlPeIl3Vs?p=preview
script.js
var app = angular.module('validationModule', []);
app.controller('mainCtrl', mainCtrl);
app.directive('testDirective', testDirective);
function testDirective(){
var testDirective = {
template: 'First Name: <input type="text" name="fName" required ng-model="user.firstName">'
};
return testDirective;
}
mainCtrl.$inject = ['$scope'];
function mainCtrl($scope){
$scope.submitForm = function(user){
alert(user.firstName + " " + user.lastName);
}
}
Index.html file
<!DOCTYPE html>
<html ng-app="validationModule">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.js" charset="UTF-8"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular-animate.js" charset="UTF-8"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular-sanitize.js" charset="UTF-8"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.3.1.js" charset="UTF-8"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="script.js"></script>
</head>
<body ng-controller="mainCtrl">
<form name="myForm" ng-submit="myForm.$valid? submitForm(user) : ''" novalidate>
<h1>Input User Name</h1><br/>
<test-directive></test-directive><br/>
Last Name: <input type="text" name="lName" required ng-model="user.lastName">
<button type="submit" class="btn btn-danger">Submit</button>
<div class="alert alert-danger" ng-show="myForm.$submitted">
<div ng-show="myForm.fName.$error.required">
First Name is required
</div>
<div ng-show="myForm.lName.$error.required">
Last Name is required
</div>
</div>
<br/><br/><br/>
<h1>Is form valid? {{myForm.$valid}}</h1>
</form>
</body>
</html>

Related

Javascript: Move JQuery etc. CDNs out of the HTML file?

(I'm new to HTML/JS). I'm trying to clean up my HTML file to bear-bone markup and put all logic in a .js file, including the CDN inclusions. I'm aware of How to include CDN in javascript file (*.js)?
In the HTML below, I tried to move the 2 'src' lines at the bottom, to form_validation.js, also shown below. But when I do that, the Semantic UI form validation stops working and I get error messages that .form is not a function etc. That addCDN() call in the JS file doesn't do it.
I imagine this has to do with me not understanding the order in which these things are processed by the browser... I would greatly appreciate some education.
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css">
<style>.container {margin: 15em;}</style>
</head>
<body>
<div class="container">
<form class="ui form">
<p>Give this a try:</p>
<div class="field">
<label>Name</label>
<input placeholder="Your Name?" name="name" type="text">
</div>
<div class="ui submit button">Submit</div>
<div class="ui error message"></div>
</form>
</div>
<!-- get these guys out-a-here -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
<!-- ..... -->
<script src="form_validation.js"></script>
</body>
</html>
/*
* form_validation.js
* Uses Semantic UI validation JSON
*/
function addCDN(){
// Can be removed? Ideally not in the HTML file...
var jq = document.createElement('script');
jq.setAttribute('src',
'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'
);
document.head.appendChild(jq);
var sui = document.createElement('script');
sui.setAttribute('src',
'https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js'
);
document.head.appendChild(sui);
}
$(document).ready(function(){
addCDN(); // this doesn't seem to happen :(
$('.ui.form').form({
fields: {name : ['minLength[6]', 'empty']}
});
});```

How to show angular input error state outside of form

I have the requirement, that all error messages have to be shown in the header of the application. How can I do that with angular?
If I have this application (see on plunker):
<body>
<div id="header">
<!-- I want error messages to show up here -->
</div>
<form name="myForm">
<label>Email</label>
<input name="myEmail" type="email" ng-model="user.email" required="" />
<div ng-messages="myForm.myEmail.$error">
<div ng-message="required">required</div>
<div ng-message="email">invalid email</div>
</div>
</form>
<p>Your email address is: {{user.email}}</p>
</body>
What I need is to have the error messages in the header div. How can I do that?
Fixed demo here.
Just access the error the way same as in form, as when you set <form name="myForm" >, then you will get $scope.myForm = [yourFormObject], then access free anywhere in same controller.
Angular Form Document
Under the title Binding to form and control state
A form is an instance of FormController. The form instance can optionally be published into the scope using the name attribute.
And, even access the $error in controller by $scope.$watch('formName.fieldName.$error',function(nv,ov){});
// Code goes here
var app = angular.module('plunker', ['ngMessages']);
app.controller('appCtrl', function($scope) {
$scope.$watch('myForm.myEmail.$error', function(nv, ov) {
console.info(nv);
}, true);
});
/* Styles go here */
hr {
margin: 20px 0;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
</script>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular-messages.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="appCtrl">
<div id="header">
<div ng-show="myForm.myEmail.$error.required">required</div>
<div ng-show="myForm.myEmail.$error.email">invalid email</div>
</div>
<hr />
<form name="myForm">
<label>Email</label>
<input name="myEmail" type="email" ng-model="user.email" required="" />
<div ng-messages="myForm.myEmail.$error">
<div ng-message="required">required</div>
<div ng-message="email">invalid email</div>
</div>
</form>
<p>Your email address is: {{user.email}}</p>
</body>
</html>
You'll have two distinct controller.In header controller, you'll be displaying your error messages.
Then your controller will be communicating over either $rootScope or service

angular expressions do not work inside the controller scope

I am facing a strange problem with the below code..
whenever I remove the ng-controller="page" from the body tag, the expressions start getting evaluated. But on applying this controller on body tag, the expressions tend to get printed as text rather than being evaluated.
Below is my relevant code (Snippet):
<html ng-app="app">
<head>
<!-- links removed for brevity -->
<script>
var app = angular.module('app',[]);
app.controller('page',function($scope){
$scope.segment.name = 'asdf';
});
</script>
</head>
<body ng-controller="page" style="padding:0px;">
<!-- additional markup removed for brevity -->
<form class="navbar-form navbar-right" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter Portal ID" ng-model="page.segment.name"/>
</div>
<button class="btn btn-default">Search {{page.segment.name}}</button>
</form>
</body>
</html>
I am possibly making some blunder in the above code as the below code which I wrote as proof of concept works well.
POC code (Snippet):
<html ng-app="app">
<head>
<!-- links removed for brevity -->
</head>
<body ng-controller="page">
<a>Name : {{page.segment.name}}</a>
<input type = "text" ng-model="page.segment.name"/>
</body>
<!-- links removed for brevity -->
<script>
var app = angular.module('app',[]);
app.controller('page',['$scope',function($scope){}]);
</script>
</html>
Kindly help
Thanks in advance..
You are probably getting an error in the console. I would guess it's something similar to "Cannot set property 'name' of undefined." What you are doing here is not valid:
$scope.segment.name = 'asdf';
You need to either do this:
$scope.segment = {};
$scope.segment.name = 'asdf';
Or this:
$scope.segment = { name: 'asdf' };
You have to create the segment object explicitly before you attempt to set properties on it.

ng-click event doesn't seem to fire in simple Angular app

I'm learning Angular through a YouTube tutorial series. In the tutorial, you create username and password inputs, and then you use a controller and ngRoute to bring up a dashboard.html page when successful credentials are used. The problem is that when clicking the button, nothing happens, whether the proper credentials are entered or not. Everything is working on the tutorial, and I have triple checked the code thoroughly, and mine looks just like the code in the tutorial. I'm sure I must be missing something though.
What I think:
There is an issue with the click event firing, so maybe there is an issue with how I am calling the function?
The tutorial uses an older angular version (1.3.14), and maybe things have changed? I'm using 1.4.9, but I looked up the api data for the ng-click directive, and all seems well. I also tried using the older version to no avail.
I'm doing something wrong with ngRoute, potentially $scope misuse?
I am inserting all of the code below. Thanks for taking a look!
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Place Title Here</title>
<meta charset = "utf-8"/>
<meta http-equiv="X-UA-compatible" content="IE-edge, chrome=1">
<meta name = "viewport" content = "width = device - width, initial-scale = 1.0"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script src="angular-route.min.js"></script>
<script src="controller.js"></script>
</head>
<body ng-app="mainApp">
<div ng-view></div>
</body>
</html>
login.html
<div ng-controller="loginCtrl"></div>
<form action="/" id="myLogin">
Username: <input type="text" id="username" ng-model="username"><br>
Password: <input type="password" id="password" ng-model="password"><br>
<button type="button" ng-click="submit()">Login</button>
</form>
controller.js
var app = angular.module('mainApp', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'login.html'
})
.when('/dashboard', {
templateUrl: 'dashboard.html'
})
.otherwise({
redirectTo: '/'
});
});
app.controller('loginCtrl', function($scope, $location) {
$scope.submit = function() {
var uname = $scope.username;
var password = $scope.password;
if($scope.username == 'admin' && $scope.password == 'admin') {
$location.path('/dashboard');
}
else {
alert('Nope')
}
};
});
dashboard.html
Welcome User.
Your form needs to be inside the div with ng-controller
<div ng-controller="loginCtrl">
<form action="/" id="myLogin">
Username: <input type="text" id="username" ng-model="username"><br>
Password: <input type="password" id="password" ng-model="password"><br>
<button type="button" ng-click="submit()">Login</button>
</form>
</div>
Otherwise it won't have access to the submit() function.

Beginners help to Angular JS debugging via console errors

AngularJS is new to me (and difficult). So I would like to learn how to debug.
Currently I'm following a course and messed something up. Would like to know how to interpret the console error and solve the bug.
plnkr.co code
index.html
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainController">
<h1>{{message}}</h1>
{{ username }}
<form action="searchUser" ng-submit="search(username)">
<input type="search"
required placeholder="Username to find"
ng-model="username"/>
<input type="submit" value="search">
</form>
<div>
<p>Username found: {{user.name + error}}</p>
<img ng-src="http://www.gravatar.com/avatar/{{user.gravatar_id}}" title="{{user.name}}"/>
</div>
</body>
</html>
script.js
(function() {
var app = angular.module("githubViewer", []);
var MainController = function($scope, $http) {
var onUserComplete = function(response) {
$scope.user = response.data;
};
var onError = function(reason) {
$scope.error = "could not fetch data";
};
$scope.search = function(username) {
$http.get("https://api.github.com/users/" + username)
.then(onUserComplete, onError);
};
$scope.username = "angular";
$scope.message = "GitHub Viewer"; };
app.controller("MainController", MainController);
}());
The console only says
searchUser:1 GET http://run.plnkr.co/lZX5It1qGRq2JGHL/searchUser? 404
(Not Found)
Any help would be appreciated.
In your form, action you have written this
<form action="searchUser"
What this does is it will try to submit to a url with currentHostName\searchUser, so in this case your are testing on plunker hence the plunker url.
You can change the url where the form is submitted. Incase you want to search ajax wise then you dont even need to specify the action part. You can let your service/factory make that call for you.
Though not exactly related to debugging this particular error, there is a chrome extension "ng-inspector" which is very useful for angularJS newbies. You can view the value each of your angular variable scopewise and their value. Hope it helps!
Here is the link of the chrome extension: https://chrome.google.com/webstore/detail/ng-inspector-for-angularj/aadgmnobpdmgmigaicncghmmoeflnamj?hl=en
Since you are using ng-submit page is being redirected before the response arrives and you provided any action URL as searchUser which is not a state or any html file so it being used to unknown address, it is async call so it will take some time you can use input types as button instead of submit.
Here is the working plunker.
<!DOCTYPE html>
<html ng-app="githubViewer">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainController">
<h1>{{message}}</h1>
{{ username }}
<form >
<input type="search"
required placeholder="Username to find"
ng-model="username"/>
<input type="button" ng-click="search(username)" value="search">
</form>
<div>
<p>Username found: {{user.name + error}} {{user}}</p>
<img ng-src="http://www.gravatar.com/avatar/{{user.gravatar_id}}" title="{{user.name}}"/>
</div>
</body>
</html>

Categories