Add several emails and diplay defined values - angularjs

My form allows to update and add several emails. The first email field (main email) is mandatory. After filling it's possible to click on a button "Add email" for adding a new email address. By this way it's possible to add 4 others emails (5 emails in total).
The system checks if the format of the email is correct and displays a message if necessary and register the data in a DB.
Here my view (manageContact.html)
<div class="panel-body">
<form name="ContactForm" class="form-horizontal" role="form" novalidate ng-submit="submitForm(contact)">
<!---------------- FOR UPDATING EMAILS FIELDS ------------ START --->
<div ng-repeat="(key, email) in emails | limitTo : 5" style="z-index:6">
<div class="form-group">
<span ng-switch="$index">
<label ng-switch-when="0" for="txtEmail" class="col-sm-2 control-label">Main email</label>
<label ng-switch-default for="txtEmail" class="col-sm-2 control-label">Email {{$index+1}}</label>
</span>
<div class="col-sm-9" ng-switch="$index">
<input ng-switch-when="0" type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter main email"
ng-model="contact.EMAIL">
<input ng-switch-default type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter Email {{$index+1}}"
ng-model="contact['EMAIL_'+$index]">
<div class="error-container"
ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$invalid">
<div ng-show="ContactForm['txtEmail_' + $index].$error.email" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
That is not a valid email. Please input a valid email.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.required" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required.
</div>
</div>
</div>
<div class="col-sm-1" ng-show="$index == 0">
<a href="" ng-click="add()" ng-show="emails.length<5" class="inline btn btn-primary icon_email">
<span class="glyphicon glyphicon-plus icon2"></span><span class="addButton">Add email</span>
</a>
</div>
</div>
</div>
<!---------------- FOR UPDATING EMAILS FIELDS ------------ END --->
</form>
</div>
In order to see all emails registered of the contact, it's necessary with my current script to click on the button "Add email" each time that an email is registered for seeing data.
I would like to display the emails if they exist in the DB - so display each time the row (field + data). If it doesn't exist it's necessary to click on the button for adding an new email.
I have problem for doing that into my ng-switch and I don't how to do that in another way.
Here my controlers "ctrlEditContacts" and module (app.js):
var app=angular.module('ContactsApp', ['ngRoute', 'ui.bootstrap', 'ngDialog']);
app.factory('HttpInterceptor', ['$q', '$rootScope', function($q, $rootScope) {
return {
......
}
};
app.config(function($routeProvider, $httpProvider, ngDialogProvider){
...
});
app.controller('ctrlEditContacts', function ($scope, $routeParams, MyTextSearch, ContactService, ngDialog, $timeout){
//FOR ALLOWING SEVERAL EMAILS
$scope.emails = [
{
}];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push(dataObj);
}
ContactService.loadPersonById($routeParams.contactId).success(function(contact){
$scope.contact.ID = contact[0].ID;
$scope.contact.EMAIL = contact[0].EMAIL;
$scope.contact.EMAIL_1 = contact[0].EMAIL_1;
$scope.contact.EMAIL_2 = contact[0].EMAIL_2;
$scope.contact.EMAIL_3 = contact[0].EMAIL_3;
$scope.contact.EMAIL_4 = contact[0].EMAIL_4;
})
.error(function (data, status, header, config) {
...
}).finally(function() {
...
});
$scope.submitForm = function(contact){
if($scope.ContactForm.$valid){
ContactService.updatePerson(contact, $routeParams.contactId).success(function(){
alert('Person updated successfully');
})
.error(function (data, status, header, config) {
})
.finally(function() {
});
}
};
});

Sorry if I'm misunderstanding.
In this case, you need to loop for the number of contact's email info.
For example, if you get a kind of data below; you need to loop three times.
$scope.contact.ID = contact[0].ID;
$scope.contact.EMAIL = contact[0].EMAIL; // 'test1#mail.com'
$scope.contact.EMAIL_1 = contact[0].EMAIL_1; // 'test2#mail.com'
$scope.contact.EMAIL_2 = contact[0].EMAIL_2; // 'test3#mail.com'
$scope.contact.EMAIL_3 = contact[0].EMAIL_3; // ''
$scope.contact.EMAIL_4 = contact[0].EMAIL_4; // ''
// So 'emails' should be modified at this timing.
$scope.emails = [];
// Just for loop, so it doesn't matter what value you add.
$scope.emails.push($scope.contact.EMAIL);
$scope.emails.push($scope.contact.EMAIL_1);
$scope.emails.push($scope.contact.EMAIL_2);
After that, changing 'Add email' condition.
ng-show="$index == emails.length - 1"
jsfiddle

Related

AngularJS Form - How to create and update several emails with ng-switch

I have a form in order to add / update one or several emails. The first email field is mandatory. After filling the field it's possible to click on "Add email" for adding a new email address. By this way it's possible to add 4 others emails (5 emails in total).
The system can verify if the format of the email is correct and display a message if necessary and register the data in a DB.
Here my view (manageContact.html)
<h3>{{title}}</h3>
<div class="panel panel-default" ng-show="authorRole==1">
<div class="panel-heading">
<div class="panel-title">Person Sheet</div>
</div>
<div class="panel-body">
<form name="ContactForm" class="form-horizontal" role="form" novalidate ng-submit="submitForm(contact)">
<!---------------- FOR UPDATING EMAILS FIELDS ------------ START --->
<div ng-repeat="(key, email) in emails | limitTo : 5" style="z-index:6">
<div class="form-group">
<span ng-switch="$index">
<label ng-switch-when="0" for="txtEmail" class="col-sm-2 control-label">Main email</label>
<label ng-switch-default for="txtEmail" class="col-sm-2 control-label">Email {{$index+1}}</label>
</span>
<div class="col-sm-9" ng-switch="$index">
<input ng-switch-when="0" type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter main email"
ng-model="contact.EMAIL">
<input ng-switch-default type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter Email {{$index+1}}"
ng-model="contact['EMAIL_'+$index]">
<div class="error-container"
ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$invalid">
<div ng-show="ContactForm['txtEmail_' + $index].$error.email" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
That is not a valid email. Please input a valid email.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.required" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.minlength" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required to be at least 3 characters
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.maxlength" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email cannot be longer than 20 characters
</div>
</div>
</div>
<div class="col-sm-1" ng-show="$index == 0">
<a href="" ng-click="add()" ng-show="emails.length<5" class="inline btn btn-primary icon_email">
<span class="glyphicon glyphicon-plus icon2"></span><span class="addButton">Add email</span>
</a>
</div>
</div>
</div>
<!---------------- FOR UPDATING EMAILS FIELDS ------------ END --->
</form>
</div>
</div>
For adding a contact all is working and the emails are correctly registered.
For updating a contact I have a problem with the contact's emails. In order to see all emails registered of the contact, it's necessary with my current script to click on the button "Add email" each time that an email is registered for seeing data.
I would like to display the emails if they exist in the DB - so display each time the row (field + data). If it doesn't exist it's necessary to click on the button for adding an new email.
Could you please help me to update this code for doing that because I cannot do that directly in ng-switch?
Here my controlers "ctrlEditContacts" and module (app.js):
var app=angular.module('ContactsApp', ['ngRoute', 'ui.bootstrap', 'ngDialog']);
app.factory('HttpInterceptor', ['$q', '$rootScope', function($q, $rootScope) {
return {
......
}
};
app.config(function($routeProvider, $httpProvider, ngDialogProvider){
$httpProvider.defaults.cache = false;
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
$httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
$routeProvider.when('/add-contacts',
{
templateUrl: 'template/manageContact.html',
controller: 'ctrlAddContacts'
})
.when('/edit-contacts/:contactId',
{
templateUrl: 'template/manageContact.html',
controller: 'ctrlEditContacts'
})
.otherwise({redirectTo:'/all-requests'});
});
app.controller('ctrlAddContacts', function ($scope, ContactService){
$scope.title="Add a contact";
// Allow to create several fields EMAIL
$scope.emails = [
{
}];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push(dataObj);
}
$scope.submitForm = function(contact){
if($scope.ContactForm.$valid){
// Send the object to the backend for saving data
ContactService.addNewPerson(contact).success(function(Person){
$scope.ContactForm.$setPristine();
$scope.contact= Person;
});
}
}
});
app.controller('ctrlEditContacts', function ($scope, $routeParams, MyTextSearch, ContactService, ngDialog, $timeout){
//FOR ALLOWING SEVERAL EMAILS
$scope.emails = [
{
}];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push(dataObj);
}
$scope.contact={};
if($routeParams.contactId){
$scope.title="Edit the contact";
}
ContactService.loadPersonById($routeParams.contactId).success(function(contact){
$scope.contact.ID = contact[0].ID;
$scope.contact.EMAIL = contact[0].EMAIL;
$scope.contact.EMAIL_1 = contact[0].EMAIL_1;
$scope.contact.EMAIL_2 = contact[0].EMAIL_2;
$scope.contact.EMAIL_3 = contact[0].EMAIL_3;
$scope.contact.EMAIL_4 = contact[0].EMAIL_4;
})
.error(function (data, status, header, config) {
console.log("Query loadPersonById ERROR");
console.log("status:" + status);
if (status==302) {
alert("Session expired - New Authentication requested");
}
}).finally(function() {
});
$scope.submitForm = function(contact){
if($scope.ContactForm.$valid){
ContactService.updatePerson(contact, $routeParams.contactId).success(function(){
alert('Person updated successfully');
})
.error(function (data, status, header, config) {
})
.finally(function() {
});
}
};
});
Here my factory (appService.js)
app.factory('ContactService', function($http){
var factory={};
factory.addNewPerson=function(objContact){
return $http.get('http://myapp/contacts.cfc?method=addNewPerson&jsStruct=' + JSON.stringify(objContact))
};
factory.updatePerson=function(objContact,id){
var params = {
method: "updatePerson",
contactid: id,
jsStruct: objContact
};
var config = { params: params };
return $http.get('http://myapp/contacts.cfc', config)
};
return factory;
})
If you have a best solution than ng-switch for doing that, please tell me.
Thank you in advance for your help.
Populate $scope.emails inside ContactService.loadPersonById()
I updated the controller:
app.controller('ctrlEditContacts', function ($scope, $routeParams, ContactService, ngDialog, $timeout){
//FOR ALLOWING SEVERAL EMAILS
$scope.emails = [];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push({});
};
$scope.contact={};
if($routeParams.contactId){
$scope.title="Edit the contact";
$scope.edit_oldContact = "true";
}
ContactService.loadPersonById($routeParams.contactId).success(function(contact){
console.log("Query loadPersonById OK");
$scope.contact.ID = contact[0].ID;
$scope.contact.EMAIL = contact[0].EMAIL;
$scope.contact.EMAIL_1 = contact[0].EMAIL_1;
$scope.contact.EMAIL_2 = contact[0].EMAIL_2;
$scope.contact.EMAIL_3 = contact[0].EMAIL_3;
$scope.contact.EMAIL_4 = contact[0].EMAIL_4;
// GET the emails already registered for displaying in the contact edit form
if($scope.contact.EMAIL.length > 0) {
$scope.emails.push($scope.contact.EMAIL);
}
if($scope.contact.EMAIL_1.length > 0) {
$scope.emails.push($scope.contact.EMAIL_1);
}
if($scope.contact.EMAIL_2.length > 0) {
$scope.emails.push($scope.contact.EMAIL_2);
}
if($scope.contact.EMAIL_3.length > 0) {
$scope.emails.push($scope.contact.EMAIL_3);
}
if($scope.contact.EMAIL_4.length > 0) {
$scope.emails.push($scope.contact.EMAIL_4);
}
})
.error(function (data, status, header, config) {
console.log("Query loadPersonById ERROR");
console.log("status:" + status);
}).finally(function() {
console.log("Query loadPersonById Finalized");
});
$scope.submitForm = function(contact){
//console.log(contact);
};
});
And The template:
<!---------------- FOR UPDATING EMAILS FIELDS ------------ START --->
<div ng-repeat="(key, email) in emails | limitTo : 5" style="z-index:6">
<div class="form-group">
<span ng-switch="$index">
<label ng-switch-when="0" for="txtEmail" class="col-sm-2 control-label">Main email</label>
<label ng-switch-default for="txtEmail" class="col-sm-2 control-label">Email {{$index+1}}</label>
</span>
<div class="col-sm-9" ng-switch="$index">
<input ng-switch-when="0" type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter main email"
ng-model="contact.EMAIL">
<input ng-switch-default type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter Email {{$index+1}}"
ng-model="contact['EMAIL_'+$index]">
<div ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$error.emailExists" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
This email is already used
<ul id="contacts_list">
<li ng-repeat=" cont in ContactForm['txtEmail_' + $index].persons" style="position:relative; z-index:1">
<div angular-popover direction="right" template-url="template/popover.html" mode="mouseover">
{{ cont.lastname }} {{ cont.firsttname }}
</div>
</li>
</ul>
</div>
<div ng-if="ContactForm['txtEmail_' + $index].$pending.emailExists">checking....</div>
<div class="error-container"
ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$invalid">
<div ng-show="ContactForm['txtEmail_' + $index].$error.email" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
That is not a valid email. Please input a valid email.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.required" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required.
</div>
</div>
</div>
<div class="col-sm-1" ng-show="$index == emails.length - 1">
<a href="" ng-click="add()" ng-show="emails.length<5" class="inline btn btn-primary icon_email">
<span class="glyphicon glyphicon-plus icon2"></span><span class="addButton">Add</span>
</a>
</div>
</div>
</div>
<!---------------- FOR UPDATING EMAILS FIELDS ------------ END --->

AngularJS Directive for checking if email already used

I follow a solution for checking if a username is already present in the DB: defined in this topic angularjs: custom directive to check if a username exists
I put that in practice for checking if an email already exists in the DB. In my application a user can register until 5 emails.
When the user enters an email in the field, the query is correctly executed for checking if the email is already used in the database.
Some error messages have been implemented when the email format is not correct.
A message should be equally displayed when the email is already used (so present in the DB) but I have some problems for doing that (with the 5 fields for email addresses)
Here my controller:
// MY DIRECTIVE FOR CHECKING IF EMAIL IS ALREADY USED
app.directive('emailAvailable', function($timeout, $q, $http, ContactService) {
return {
restrict: 'AE',
require: 'ngModel',
link: function(scope, elm, attr, model) {
model.$asyncValidators.emailExists = function() {
email= elm.val();
return ContactService.searchContactByEmail(email).success(function(contact){
$timeout(function(){
if(contact.length >0){
model.$setValidity('emailExists', contact);
//model.$setValidity('unique', false); // For validation criteria in the form
scope.emailAlreadyExist='true';
scope.contacts = contact;
// THE VALUE IS CORRECTLY DISPLAYED IN THE CONSOLE
console.log("exist : " + scope.emailAlreadyExist);
}else{
model.$setValidity('emailExists', contact);
//model.$setValidity('unique', true); // For validation criteria in the form
scope.emailAlreadyExist='false';
scope.contacts = null;
// THE VALUE IS CORRECTLY DISPLAYED IN THE CONSOLE
console.log("exist : " + scope.emailAlreadyExist);
}
}, 600);
});
};
}
}
});
app.controller('ctrlAddContacts', function ($scope, ContactService){
$scope.title="Add a contact";
$scope.edit_oldContact = "false";
// ALLOW TO HAVE SEVERAL EMAILS
$scope.emails = [
{
}];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push(dataObj);
}
.........
});
Here my Factory:
app.factory('ContactService', function($http){
var factory={};
// CALL COLDFUSION FUNCTION
factory.searchContactByEmail=function(string){
if (string){
chaine='http://myapp/contacts.cfc?method=searchContactByEmail&contactEmail=' + string;
}else{
chaine='';
}
return $http.get(chaine);
};
return factory;
})
Here my Template:
<! --------------------------- MANAGE MAILS --------------------------->
<div ng-repeat="(key, email) in emails | limitTo : 5">
<div class="form-group">
<span ng-switch="$index">
<label ng-switch-when="0" for="txtEmail" class="col-sm-2 control-label">Main email</label>
<label ng-switch-default for="txtEmail" class="col-sm-2 control-label">Email {{$index+1}}</label>
</span>
<div class="col-sm-9" ng-switch="$index">
<input ng-switch-when="0" type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter main email"
required
ng-model="contact.EMAIL"
email-available
>
<input ng-switch-default type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter Email {{$index+1}}"
required
ng-model="contact['EMAIL_'+$index]"
email-available
>
<!-- THE VALUE emailAlreadyExist IS NOT DISPLAYED IN THE PAGE -->
<p>txtEmail_{{$index}} : {{emailAlreadyExist}}</p>
<! ----------------- Display the message when the email is already used ----------------->
<div ng-show="ContactForm['txtEmail_' + $index].$dirty && emailAlreadyExist=='true' " class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Email is already used
</div>
<div ng-if="ContactForm['txtEmail_' + $index].$pending.emailExists">checking....</div>
<! ----------------- Display the message when the email is already used ----------------->
<div class="error-container"
ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$invalid">
<div ng-show="ContactForm['txtEmail_' + $index].$error.email" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
That is not a valid email. Please input a valid email.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.required" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.minlength" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required to be at least 3 characters
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.maxlength" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email cannot be longer than 20 characters
</div>
</div>
</div>
<div class="col-sm-1" ng-show="$index == 0">
<a href="" ng-click="add()" ng-show="emails.length<5" class="inline btn btn-primary icon_email">
<span class="glyphicon glyphicon-plus icon2"></span><span class="addButton">Add</span>
</a>
</div>
</div>
</div>
<! --------------------------- MANAGE MAILS --------------------------->
Could you tell me how to update the script (of the directive I suppose) for displaying the message Email is already used ?
Thanks in advance for your help.
Please try below directive :
// MY DIRECTIVE FOR CHECKING IF EMAIL IS ALREADY USED
app.directive('emailAvailable', function($timeout, $q, $http, ContactService) {
return {
restrict: 'AE',
require: 'ngModel',
link: function(scope, elm, attr, model) {
model.$asyncValidators.emailExists = function() {
email= elm.val();
return ContactService.searchContactByEmail(email).success(function(contact){
$timeout(function(){
if(contact.length >0){
model.$setValidity('emailExists', true);
//model.$setValidity('unique', false); // For validation criteria in the form
scope.emailAlreadyExist='true';
scope.contacts = contact;
// THE VALUE IS CORRECTLY DISPLAYED IN THE CONSOLE
console.log("exist : " + scope.emailAlreadyExist);
}else{
model.$setValidity('emailExists', false);
//model.$setValidity('unique', true); // For validation criteria in the form
scope.emailAlreadyExist='false';
scope.contacts = null;
// THE VALUE IS CORRECTLY DISPLAYED IN THE CONSOLE
console.log("exist : " + scope.emailAlreadyExist);
}
}, 600);
});
};
}
}
});
and in template make following changes :
<! ----------------- Display the message when the email is already used ----------------->
<div ng-show="ContactForm['txtEmail_' + $index].$dirty && YOUR_FORM_NAME.$error.emailExists" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Email is already used
</div>
<div ng-if="ContactForm['txtEmail_' + $index].$pending.emailExists">checking....</div>
<! ----------------- Display the message when the email is already used ----------------->

angularjs scope within scope dynamic elements saving

I am having quite the trouble with scopes created by directives, and saving these dynamic elements' scope back to the parent.
Here is my directive:
app.directive('action', function() {
return {
restrict: "E",
scope: {},
templateUrl:'views/pages/projects/triggers/newaction.html',
controller: function($rootScope, $scope, $element) {
$scope.groups = $scope.$parent.groups;
$scope.scenes = $scope.$parent.scenes;
$scope.actions = $scope.$parent.actions;
$scope.Delete = function(e) {
//remove element and also destoy the scope that element
$element.remove();
$scope.$destroy();
};
}
};
});
here is my controller:
.controller('NewTriggerCtrl', ['Auth', '$scope', 'toastr', '$state', '$stateParams', 'FBURL', '$filter', '$compile',
function(Auth, $scope, toastr, $state, $stateParams, FBURL, $filter, $compile) {
var authData = Auth.$getAuth();
var ref = new Firebase(FBURL + '/projects/' + authData.uid + '/' + $stateParams.projectid);
// Submit operation
var retriveActions = function() {
// http://stackoverflow.com/questions/12649080/get-to-get-all-child-scopes-in-angularjs-given-the-parent-scope
var theseactions = [];
var ChildHeads = [$scope.$$childHead];
var currentScope;
while (ChildHeads.length) {
currentScope = ChildHeads.shift();
while (currentScope) {
/* theseactions.push({
type: currentScope.type,
data: currentScope.data,
data2: currentScope.data2
}); */
console.log("currentscope.type = " + currentScope.type);
};
currentScope = currentScope.$$nextSibling;
}
//return theseactions;
};
var retrieveactions2 = function() {
var theseactions = [];
var newevent = null;
var newdata = null;
var newdata2 = null;
console.log("in retrieve actions");
angular.forEach(angular.element(document.getElementsByClassName("newaction")), function(element){
console.log("iterating");
newevent = $(this).find('.newactionevent').value;
newdata = $(this).find('.newactiondata').value;
newdata2 = $(this).find('.newactiondata2').value;
theseactions.push({
event: newevent,
data: newdata,
data2: newdata2
});
});
return theseactions;
}
$scope.ok = function(actions) {
//console.log(retriveActions(actions));
//retriveActions(actions);
//console.log("$scope.trigger.actions = " + $scope.trigger.actions);
//console.log("actions = " + actions);
console.log(retrieveactions2());
$scope.triggers.$add($scope.trigger).then(function (triggerRef) {
ref.child('triggers').child(triggerRef.key())
.update({created_at: Firebase.ServerValue.TIMESTAMP});
toastr.success('Trigger Added!', 'Trigger has been created');
$state.go('app.projects.edit', {projectid : $stateParams.projectid}, {reload: true});
});
};
$scope.newaction = function() {
var divElement = angular.element(document.querySelector('#actions'));
var appendHtml = $compile('<action></action>')($scope);
divElement.append(appendHtml);
};
$scope.cancel = function() {
$state.go('app.projects.edit', {projectid : $stateParams.projectid}, {reload: true});
};
/////////////////////// *Submit operation
}])
here is my new trigger html:
<div class="page page-newtrigger" ng-controller="NewTriggerCtrl">
<!-- row -->
<div class="row">
<div class="col-md-12">
<!-- tile -->
<section class="tile tile-simple">
<!-- tile body -->
<div class="tile-body">
<form name="form" class="form-horizontal form-validation" role="form" novalidate>
<div class="form-group mt-12" style="margin-top: 15px;">
<label for="name" class="col-sm-1 control-label">Name <span class="text-danger" style="font-size: 15px;">*</span></label>
<div class="col-sm-1">
<input type="text" name="name" class="form-control" id="name" placeholder="Trigger name..." ng-model="trigger.name" required>
</div>
<div class="btn-group col-sm-2">
<label class="btn btn-green" ng-model="trigger.type" uib-btn-radio="'astro'">Astro</label>
<label class="btn btn-green" ng-model="trigger.type" uib-btn-radio="'time'">Real-Time</label>
<label class="btn btn-green" ng-model="trigger.type" uib-btn-radio="'input'">Input</label>
</div>
<div class="animate-switch-container" ng-switch on="trigger.type">
<div class="animate-switch" ng-switch-when="astro">
<div class="btn-group col-sm-2">
<label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'sunrise'">Sunrise</label>
<label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'sunset'">Sunset</label>
</div>
<div class="col-sm-1">
<input type="text" name="offset" class="form-control" id="offset" placeholder="Offset (+/- minutes)" ng-model="trigger.option">
</div>
</div>
<div class="animate-switch" ng-switch-when="time">
<div class="btn-group col-sm-2">
<label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'repeat'">Repeat</label>
<label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'once'">Once</label>
</div>
<div class="animate-switch-container" ng-switch on="trigger.event">
<div class="animate-switch" ng-switch-when="repeat">
<div class="col-sm-3 btn-group">
<label class="btn btn-cyan" ng-model="trigger.option.mon" uib-btn-checkbox>Mon</label>
<label class="btn btn-cyan" ng-model="trigger.option.tue" uib-btn-checkbox>Tue</label>
<label class="btn btn-cyan" ng-model="trigger.option.wed" uib-btn-checkbox>Wed</label>
<label class="btn btn-cyan" ng-model="trigger.option.thu" uib-btn-checkbox>Thur</label>
<label class="btn btn-cyan" ng-model="trigger.option.fri" uib-btn-checkbox>Fri</label>
<label class="btn btn-cyan" ng-model="trigger.option.sat" uib-btn-checkbox>Sat</label>
<label class="btn btn-cyan" ng-model="trigger.option.sun" uib-btn-checkbox>Sun</label>
</div>
<div class="col-sm-1">
<input type="text" name="time" class="form-control" id="time" placeholder="Time (HH:mm:ss)" ng-model="trigger.data">
</div>
</div>
<div class="animate-switch" ng-switch-when="once">
<div class="col-sm-2" >
<p class="input-group" ng-controller="DatepickerDemoCtrl">
<input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="trigger.option" is-open="opened" min-date="minDate" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)"><i class="fa fa-calendar"></i></button>
</span>
</p>
</div>
<div class="col-sm-1">
<input type="text" name="time" class="form-control" id="time" placeholder="Time (HH:mm:ss)" ng-model="trigger.data">
</div>
</div>
</div>
</div>
<div class="animate-switch" ng-switch-when="input">
<div class="col-sm-1">
<select ng-init="1" ng-model="trigger.option" class="form-control mb-10">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
</select>
</div>
<div class="col-sm-2">
<div class="btn-group">
<label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'high'">Goes high</label>
<label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'low'">Goes low</label>
</div>
</div>
</div>
</div>
<button class="btn btn-success b-0 pull-right" style="margin-right: 30px;" ng-click="newaction()"><i class="fa fa-plus mr-5"></i>New Action</button>
</div>
<div id="actions">
<action ng-repeat="action in trigger.actions"></action>
</div>
<div class="form-footer">
<button class="btn btn-success b-0 pull-right" ng-click="ok(trigger)" ng-disabled="form.$invalid">Submit</button>
<button class="btn btn-lightred btn-ef btn-ef-4 btn-ef-4c" ng-click="cancel()"><i class="fa fa-arrow-left"></i> Cancel</button>
</div>
</form>
</div>
<!-- /tile body -->
</section>
<!-- /tile -->
</div>
</div>
<!-- /row -->
</div>
here is my newaction html:
<!-- row -->
<div class="newaction row">
<div class="col-md-10 col-sm-offset-2">
<form name="form" class="form-horizontal form-validation" role="form" novalidate>
<div class="form-group mt-12" style="margin-top: 15px;">
<div class="col-sm-1"><button ng-click="Delete($event)" class="btn btn-danger"><i class="glyphicon glyphicon-trash"></i></button></div>
<div class="btn-group col-sm-2">
<select ng-init="1" ng-model="action.type" class="newactiontype form-control mb-10">
<option value="transition-scene">Transition Scene</option>
<option value="set-group-intensity">Set Group Intensity</option>
<option value="inject-trigger">Inject Trigger</option>
<option value="color-change">Color Change</option>
</select>
</div>
<div ng-if="action.type=='transition-scene'">
<div class="col-sm-3">
<select chosen="" class="newactionevent form-control mb-10" ng-options="scene.name for scene in scenes track by scene.name" ng-model="action.scene"></select>
</div>
<div class="col-sm-1">
<input type="text" name="fadetime" class="newactiondata form-control" id="fadetime" placeholder="Fade Time (seconds)" ng-model="action.fadetime">
</div>
</div>
<div ng-if="action.type=='set-group-intensity'">
<div class="col-sm-3">
<select multiple chosen="" class="newactionevent form-control mb-10" ng-options="group.name for group in groups track by group.name | filter: {type : 'white'}" ng-model="$parent.action.group"></select>
</div>
<div class="col-sm-1">
<input type="text" name="intensity" class="newactiondata form-control" id="intensity" placeholder="Intensity(%)" ng-model="action.intensity">
</div>
<div class="col-sm-1">
<input type="text" name="fadetime" class="newactiondata2 form-control" id="fadetime" placeholder="Fade Time (sec)" ng-model="action.fadetime">
</div>
</div>
<div ng-if="action.type=='inject-trigger'">
<div class="col-sm-2">
<input type="text" name="triggernumber" class="newactiondata form-control" id="triggernumber" placeholder="Trigger number..." ng-model="action.data">
</div>
</div>
<div ng-if="action.type=='color-change'">
<div class="col-sm-3">
<select multiple chosen="" class="newactionevent form-control mb-10" ng-options="group.name for group in groups track by group.name| filter:group.type!='white'" ng-model="action.group"></select>
</div>
<div class="col-sm-1">
<input colorpicker="rgb" ng-model="action.data" type="text" class="newactiondata form-control w-md mb-10">
</div>
<div class="col-sm-1">
<input type="text" name="fadetime" class="newactiondata2 form-control" id="fadetime" placeholder="Fade Time (sec)" ng-model="action.fadetime">
</div>
</div>
</div>
</form>
</div>
</div>
<!-- /row -->
I have multiple attempts at this, as you can see with the two different functions in NewTriggerCtrl. The first was to get all the child scopes and iterate through, however when I call this it locks the browser up with over 250,000 logs. So maybe I am passing the wrong scope?
I am relatively new to Angular, and have some experience in JQuery, and I attempted to name the inputs with classes and finding them with document calls, but that is not working either. I have an app running and I can create, detele, etc. groups, triggers (not the trigger actions), and scenes, So I understand the basics of controllers and scopes. But saving these child scopes to the main trigger (what I assume would be trigger.actions) has stumped me. Maybe there is a better way to this? I know my code may not be efficient, I am attempting to get a base then clean up later.
Thank you.
UPDATE:
Ok so new directive:
app.directive('action', function() {
return {
restrict: "E",
scope: true,
templateUrl:'views/pages/projects/triggers/newaction.html',
controller: function($rootScope, $scope, $element) {
$scope.Delete = function(e) {
console.log("$scope.action = " + $scope.action);
//remove element and also destoy the scope that element
$element.remove();
$scope.$destroy();
};
}
};
});
and entire trigger controller:
'use strict';
app
.controller('TriggersCtrl', ['Auth', '$scope', '$state', '$stateParams', '$firebaseArray', '$firebaseObject', 'FBURL',
function(Auth, $scope, $state, $stateParams, $firebaseArray, $firebaseObject, FBURL) {
// General database variable
var authData = Auth.$getAuth();
var ref = new Firebase(FBURL + '/projects/' + authData.uid + '/' + $stateParams.projectid);
$scope.triggers = $firebaseArray(ref.child('triggers'));
$scope.groups = $firebaseArray(ref.child('groups'));
$scope.scenes = $firebaseArray(ref.child('scenes'));
$scope.triggersObject = $firebaseObject(ref.child('triggers'));
//////////////////////////// *General database variable
// get the model
if($stateParams.triggerid) {
var id = $stateParams.triggerid;
$scope.trigger = $firebaseObject(ref.child('triggers').child(id));
$scope.actionsObject = $firebaseObject(ref.child('triggers').child(id).child('actions'));
} else {
$scope.trigger = {};
$scope.actionsObject = {};
}
}])
.controller('NewTriggerCtrl', ['Auth', '$scope', 'toastr', '$state', '$stateParams', 'FBURL', '$filter', '$compile', '$firebaseArray',
function(Auth, $scope, toastr, $state, $stateParams, FBURL, $filter, $compile, $firebaseArray) {
var authData = Auth.$getAuth();
var ref = new Firebase(FBURL + '/projects/' + authData.uid + '/' + $stateParams.projectid);
// Submit operation
$scope.ok = function() {
console.log("$scope.actions = " + $scope.actions);
console.log("$scope.trigger.actions = " + $scope.trigger.actions);
$scope.triggers.$add($scope.trigger).then(function (triggerRef) {
ref.child('triggers').child(triggerRef.key())
.update({created_at: Firebase.ServerValue.TIMESTAMP});
toastr.success('Trigger Added!', 'Trigger has been created');
$state.go('app.projects.edit', {projectid : $stateParams.projectid}, {reload: true});
});
};
$scope.newaction = function() {
var divElement = angular.element(document.querySelector('#actions'));
var appendHtml = $compile('<action></action>')($scope);
divElement.append(appendHtml);
};
$scope.cancel = function() {
$state.go('app.projects.edit', {projectid : $stateParams.projectid}, {reload: true});
};
/////////////////////// *Submit operation
}]);
The scopes for the actions are created, and when i delete they are logged as an object. But the actions are not saved into trigger. I tried creating an actionsObject and then ng-repeat="action in actionsObject" but that didnt work. I try $scope.trigger.actions = $scope.actionsObject (to no avail) [my thought is how I created the $scope.trigger and the $scope.actionsObject is that they should behave the same if I call "action in actionsObject" vs "action in trigger.actions"..?]. My assumption is that I append the newaction template, which it's scope is action, the ng-repeat="action in trigger.actions" part, does this create the bind for when I add the new element to #actions that it saved to the trigger.actions scope? Having "scope: true" in the directive gives me the scenes and groups perfectly (understand the inheritance a little better). I should note that I create a trigger (a single one) and add multiple actions (which groups and scenes are part of the ng-options which is why i needed those models). Does the multiple appends affect anything? This is my last major feature to work out. I appreciate the help!
Your action directive use an isolate scope, and that is for internal use by the directive only.
The data you want to save in your Actions-array (to be submitted with the form) should go directly into the action-object and not on the scope.
You can access the action-object in two ways:
Use a child scope (by specifying scope: true instead of scope: {})
This allows you to access the parent's scope variables by inheritance:
$scope.action refers to the current action object (from ng-repeat)
$scope.groups refers to the groups array from the parent scope
This means you can assign data to $scope.action.something and it will affect the action object immediately. This is the beauty of angular: Manipulate the data directly, and skip the tedious "loop through everything to get the values".
You can also use an isolate scope (using scope: {} syntax). When using an isolate scope you need to specify explicitly the variables you want to use.
{
...
scope: {
theActionObject: '=',
groupList: '=',
sceneList: '='
}
...
}
This can then be referenced in you directive's link or controller function as $scope.theActionObject.
$scope.theActionObject.something = 'test';
// Access the groups array
alert($scope.groupList.length);
And to tie it together you need to specify the references in the HTML:
<div id="actions">
<action ng-repeat="action in trigger.actions"
the-action-object="action"
group-list="groups"
scene-list="scenes"></action>
</div>
Hope this will help you!
where are your groups, scenes and actions objects defined on the $parent scope? You would need to define them in your NewTriggerCtrl
$scope.groups = [];
$scope.scenes = [];
$scope.actions = [];
Since you are isolating scope, you would normally bind them through attributes like:
scope: {groups: '=', scenes: '=', actions: '=' }
and
<action ng-repeat="action in trigger.actions" groups="groups" scenes="scenes" actions="actions"></action>
An alternative to isolate scope would be to use a prototypical inherited scope with scope: true
Either way, binding $scope.foo = $scope.$parent.foo; seems unnecessary.
Those two methods are for if you actually need new scopes for each action directive. If you don't, then you can just leave the scope property out of your action directive definition and the action directives will use whatever scope they are rendered in.

AngularJS & Laravel - Wizard navigation

I am trying to create a multi form/wizard step navigation. I am using ng-switch to create the steps. But I got stuck, this is the relevant code:
HTML:
<div ng-controller="stepCtrl">
<div ng-switch="step">
<div ng-switch-when="1">
<div ng-controller="postAddressDataCtrl">
<form url="users/createaddress" ng-submit="add()">
<label class="input-label">
<span class="label-title">
Line 1
</span>
<input type="text" name="line-1" ng-model="line1" placeholder="Line 1">
</label>
<label class="input-label">
<span class="label-title">
Line 2
</span>
<input type="text" name="line-2" ng-model="line2" placeholder="Line 2">
</label>
<label class="input-label">
<span class="label-title">
City
</span>
<input type="text" name="city" ng-model="city" placeholder="City">
</label>
<label class="input-label">
<span class="label-title">
Postcode
</span>
<input type="text" name="postcode" ng-model="postcode" placeholder="Postcode">
</label>
<label class="input-label">
<span class="label-title">
Country
</span>
<input type="text" name="country" ng-model="country" placeholder="Country">
</label>
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
{{ Form::button('Save Address', array('type'=>'submit', 'class'=>'btn btn-primary', 'style' => 'width:100%;')) }}
</div>
</form>
</div>
<button ng-click="setStep(2)">Step 2</button>
</div>
<div ng-switch-when="2">
Step 2 - another form
<button ng-click="setStep(1)">Step 1</button>
<button ng-click="setStep(3)">Step 3</button>
</div>
<div ng-switch-when="3">
Step 3 - another form
<button ng-click="setStep(2)">Step 2</button>
</div>
</div>
</div>
Controllers:
stepCtrl
myApp.controller('stepCtrl',function($scope){
$scope.step = 1;
$scope.setStep = function(step){
$scope.step = step;
}
});
postAddressDataCtrl
myApp.controller('postAddressDataCtrl', ['$scope', '$http', 'CSRF_TOKEN', function($scope, $http, CSRF_TOKEN) {
$scope.urlpath = '{{ url('/') }}';
$scope.add = function() {
var line1 = $scope.line1;
var line2 = $scope.line2;
var city = $scope.city;
var postcode = $scope.postcode;
var country = $scope.country;
return $http({
url: "/users/createaddress",
method: "POST",
data: {
'line1': line1,
'line2': line2,
'city': city,
'postcode': postcode,
'country': country,
'_token': CSRF_TOKEN
},
}).success(function(data, status, headers, config) {
console.log(data);
if (data.status == 200) {
// move to the next step
}
}).error(function(data, status, headers, config) {
console.log(data);
});
};
}]);
How can I check if the data entered in the form are valid and if they are then to move in the next step with a single button?
How can I set the step equal to 2 when the data.status is equal to 200, so only then it will move on?
Use Angular's form validation. For example add required to your input field if you want to require the field and ng-minlength or ng-maxlength for character limits. You can also write custom validation if you need specific validation on certain fields.
To change the step you can increment your step variable inside ng-submit.
To increment only if your $http request is successful you can put it directly in your .success function.
<form url="users/createaddress" ng-submit="add()" novalidate>
<label class="input-label">
<span class="label-title">
Line 1
</span>
<input type="text" name="line-1" ng-model="line1" placeholder="Line 1" ng-minlength=3 ng-maxlength=20 required>
</label>
<button type="submit" class="btn btn-primary">Save Address</button>
</form>
postAddressDataCtrl
myApp.controller('postAddressDataCtrl', ['$scope', '$http', 'CSRF_TOKEN', function($scope, $http, CSRF_TOKEN) {
$scope.urlpath = '{{ url('/') }}';
$scope.add = function() {
var line1 = $scope.line1;
var line2 = $scope.line2;
var city = $scope.city;
var postcode = $scope.postcode;
var country = $scope.country;
return $http({
url: "/users/createaddress",
method: "POST",
data: {
'line1': line1,
'line2': line2,
'city': city,
'postcode': postcode,
'country': country,
'_token': CSRF_TOKEN
},
}).success(function(data, status, headers, config) {
console.log(data);
if (data.status == 200) {
// move to the next step
$scope.step += 1;
}
}).error(function(data, status, headers, config) {
console.log(data);
});
};
}]);

Angularjs form submition with post and catching response , redirecting different view or displaying response on the same the view

I am new to angularjs, I am trying to use $http.post and want display the response in the same view or different view by using ng-show directive.
Control is coming to success and displaying divsion and immediatly disappearing. Please help me.
Thanks in advance.
var myapp = angular.module('registrationApp', [ 'ngRoute' ]);
// create angular controller
myapp.controller('mainController', function($scope, $http) {
$scope.regStatus =false;
// function to submit the form after all validation has
// occurred
$scope.submitForm = function() {
user = {
"type" : "admin",
"emailid" : $scope.user.email,
};
var res = $http.post('/fosiness-web/services/user/registeruser', user);
res.success(function(data, status, headers, config) {
alert("Success : " + JSON.stringify({
data : data }));
debugger;
$scope.mydata = data;
$scope.regStatus = true;
});
res.error(function(data, status, headers, config) {
alert("failure message: " + JSON.stringify({
data : data
}));
});
}
});
<div class="container" style="background-color: #E8E8E8;"
ng-app="registrationApp" ng-controller="mainController">
...................
<div class="alert alert-success" ng-show="regStatus">
× Success <strong ng- model="user.message.description">{{mydata}} {{regStatus}}</strong>
</div>
<form id="registrationForm" method="post" method="POST"
novalidate
class="form-horizontal registerForm"
data-bv-feedbackicons-valid="glyphicon glyphicon-ok"
data-bv-feedbackicons-invalid="glyphicon glyphicon-remove"
data-bv-feedbackicons-validating="glyphicon glyphicon-refresh">
<div class="form-group">
<label class="col-sm-3 control-label">Email-Id</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="email"
ng-model="user.email" data-bv-notempty="true"
data-bv-notempty-message="The email address is required and cannot be empty"
data-bv-emailaddress="true"
data-bv-emailaddress-message="The email address is not a valid" />
</div>
......................
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<!-- Do NOT use name="submit" or id="submit" for the Submit button -->
<button type="submit" class="btn btn-info"
ng-click="submitForm()">Sign up</button>
<button type="reset" class="btn btn-warning">Reset</button>
</div>
</div>
</form>
</div>

Resources