I'm building a simple to do app in order to better understand some AngularJS fundamentals.
I have two views, home and new item.
In the new item view, I have a form, which uses a function on ng-submit call addNewToDoTask.
When the form is submitted it should execute this function, which will in turn update an object with the input values.
I will then use these values by means of a service, to show the new object on the home page.
But it appears nothing is being pushed into the taskArr array.
I've stepped through and debugged and the issue seems to be that the function in ng-submit is not being called at all when I click my submit button.
The button is of type submit it is also inside of the form, so I'm not sure what I'm doing wrong here.
New item html
<div ng-controller="newItemCtrl">
<div class="row header">
<div class="col-12">
<h1>DOINGO</h1>
</div>
</div>
<div class="row addNewItem">
<form class="form" ng-submit="addNewToDoTask()">
<div class="row projectInput text-center">
<div class="col-12">
<input type="text" ng-model="projectInput" placeholder="Enter a project title">
</div>
</div>
<div class="row taskInput text-center">
<div class="col-12">
<input type="text" ng-model="taskInput" placeholder="Enter your task details">
</div>
</div>
</div>
<div class="buttonRow row">
<div class="col-12 text-center">
<button type="submit" class="btn-lg btn-success addItemButton">Add</button>
</form>
<button class="btn-lg btn-danger cancelButton">Cancel</button>
<button class="btn-lg btn-info addItemButton">Open Tasks</button>
</div>
</div>
</div>
app.module.js
var app = angular.module('ToDoListApp', ['ngRoute']);
app.config(function ($routeProvider, $locationProvider) {
$locationProvider.hashPrefix('');
$routeProvider
.when("/", {
templateUrl: "app/home/homePage.html",
})
.when("/newItem", {
templateUrl: "app/newItem/newitem.html",
})
.otherwise({
redirectTo: '/'
});
});
//controller for home page
app.controller('homePageCtrl', function ($scope, newToDoTaskService) {
$scope.toDoList = newToDoTaskService.getTasks();
});
//controller for new item page
app.controller('newItemCtrl', function ($scope, newToDoTaskService) {
$scope.addNewToDoTask = function () {
newToDoTaskService.addTask({
project: $scope.projectInput,
task: $scope.taskInput,
done: false
});
$scope.projectInput = "";
$scope.taskInput = "";
};
});
//service to persist data across views
app.service('newToDoTaskService', function () {
var taskArr = [];
this.getTasks = function () {
return taskArr;
};
this.addTask = function (task) {
taskArr.push(task);
};
});
The ng-submit function is not executing because the submit button is not part of the form:
ERRONEOUS
<div ng-controller="newItemCtrl">
<div class="row header">
<div class="col-12">
<h1>DOINGO</h1>
</div>
</div>
<div class="row addNewItem">
<form class="form" ng-submit="addNewToDoTask()">
<div class="row projectInput text-center">
<div class="col-12">
<input type="text" ng-model="projectInput" placeholder="Enter a project title">
</div>
</div>
<div class="row taskInput text-center">
<div class="col-12">
<input type="text" ng-model="taskInput" placeholder="Enter your task details">
</div>
</div>
<!-- FORM tag closes early here -->
</div>
<div class="buttonRow row">
<div class="col-12 text-center">
<button type="submit" class="btn-lg btn-success addItemButton">Add</button>
<!-- FORM CLOSING tag ignored -->
</form>
<button class="btn-lg btn-danger cancelButton">Cancel</button>
<button class="btn-lg btn-info addItemButton">Open Tasks</button>
</div>
</div>
</div>
The </div> closing tag closes the <form> element early. The HTML5 parser ignores the subsequent </form> closing tag.
The submit event event listener on the <form> element does not get the event because the submit button dispatches its submit event from outside the form.
Related
Here I am sending data of mail id and its visibility to server for two different users for one I have included mail and its visibility and for another hiding visibility.
To hide visibility I am using <div ng-if="atom.type === 'person'">.
Hiding and showing is working properly but problem is that on both case
it is showing visibility undefined.
If I am not using <div ng-if="atom.type === 'person'">. then it is properly sending visibility.
How to resolve this?
My Code is bolow
var myApp = angular.module('myApp', ['ngMessages']);
myApp.controller('profileInfo', function($scope, $http) {
$scope.authorized = false;
$scope.visibility = ["Private", "Friends", "Public"];
$scope.id = 0;
$atom.type = 'person';
$scope.addMailId = function(data) {
console.log(data);
$scope.mailidDetaillD = {
'mailidDetaillList[0].email': data.mailid,
'mailidDetaillList[0].visibility': data.visibility,
'pageId': $scope.id,
};
console.log($scope.mailidDetaillD);
}
});
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular-messages.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular.min.js"></script>
<dd class="col-sm-7 col-md-7 col-lg-7">
<div class="pull-right" ng-if="authorized">
<a ng-click="showAddMailIdDiv()" ng-model="addMailIdLink">add MailId Details</a>
<div class="add-school" ng-show="showAddMailId">
<form action="AddMailId" id="AddMailId" name="addmail" cssClass="form-horizontal">
<div class="form-group">
<div class="col-lg-2">
<label>Mail Id</label>
</div>
<div class="col-lg-6">
<input type="text" ng-model="mail.mailid" name="mailid" placeholder="Enter mail id" required class="form-control" />
<div ng-messages="addmail.mailid.$error" ng-if="addmail.mailid.$touched">
<p class="field-err" ng-message="required">MailId Required</p>
</div>
</div>
</div>
<div ng-if="atom.type === 'person'">
<div class="form-group">
<div class="col-lg-2">
<label>Visibility</label>
</div>
<div class="col-lg-6">
<select ng-model="mail.visibility"
ng-init=" mail.visibility = visibility[1]"
ng-options="x for x in visibility"
class="form-control"
name="mailvisibility" required>
</select>
<div ng-messages="addmail.mailvisibility.$error" ng-if="addmail.mailvisibility.$touched">
<p class="field-err" ng-message="required">Select Mail visibility</p>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-2">
<label class="sr-only">Submit</label>
</div>
<div class="col-lg-6 pull-right">
<input type="button" value="add" ng-click="addMailId(mail)" ng-disabled="addmail.$invalid" cssClass="btn btn-sm btn-primary" />
<input type="button" ng-click="hideAddMailIdDiv()" value="cancle" class="btn btn-sm btn-secondary" />
</div>
</div>
</form>
</div>
</div>
</dd>
last console.log is showing following result
mailidDetaillList[0].email: "W#w.com"
mailidDetaillList[0].visibility: undefined
pageId: 2337
after removing <div ng-if="atom.type === 'person'">
mailidDetaillList[0].email: "ss#s.com"
mailidDetaillList[0].visibility: "Public"
pageId: 2337
Delete the ng-init:
<select ng-model="mail.visibility"
̶n̶g̶-̶i̶n̶i̶t̶=̶"̶ ̶m̶a̶i̶l̶.̶v̶i̶s̶i̶b̶i̶l̶i̶t̶y̶ ̶=̶ ̶v̶i̶s̶i̶b̶i̶l̶i̶t̶y̶[̶1̶]̶"̶
ng-options="x for x in visibility"
class="form-control"
name="mailvisibility" required>
</select>
And set visibility from the controller:
$scope.mail = { visibility: $scope.visibility[1] };
AngularJS is an MVC - Model-View-Controller framework. The framework renders the View from the Model. The Controller creates the Model. Using ng-init to create the Model is going the wrong way. It makes an App that is difficult to understand, test, debug, and maintain.
The ng-init directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit. See AngularJS ng-init Directive API Reference.
I have a submit button on my form but for some weird reason it requires me to click on the button twice before it calls the save function underneth, I am using Pug for my HTML
Here is my HTML template:
<form ng-submit="save()">
<div class="form-group">
<div class="row">
<div class="col col-md-6">
<ol ng-model="service.category" title="Select a category" class="nya-bs-select">
<li nya-bs-option="category in categories.rows" class="nya-bs-option"><a> <span>{{category.name}} </span><span class="glyphicon glyphicon-ok check-mark"></span></a></li>
</ol>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col col-md-6">
<div class="input-group"><span class="input-group-addon">Service Name</span>
<input type="text" ng-model="service.name" class="form-control"/>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col col-md-6">
<textarea ng-model="service.description" placeholder="Service Description" rows="10" class="form-control"></textarea>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col col-md-6">
<button type="submit" value="Save" class="btn btn-default"> Save</button>
</div>
</div>
</div>
</form>
The save function called is as
angular.module('App.controllers')
.controller('UpdateServiceCtrl', [
'$scope', '$state', 'ServicesService', 'Notification',
function ($scope, $state, ServicesService, Notification) {
$scope.service = $scope.$parent.service;
$scope.categories = $scope.$parent.categories;
/**
* Edits a service
* #param {integer} serviceID Id of the service to be edited
* #return {undefined} Does not return any values
*/
$scope.save = function () {
$scope.service.category_id = $scope.service.category.id;
ServicesService.save($scope.service, $scope.service.id)
.then(function (result) {
$state.reload();
})
}
}]);
You can disable the submit button after it clicked first time using
ng-disabled='isButtonEnabled' your html.
Modify your save like this
$scope.save = function () {
$scope.isButtonEnabled = false;
$scope.service.category_id = $scope.service.category.id;
ServicesService.save($scope.service, $scope.service.id)
.then(function (result) {
$state.reload();
})
}
Let me know if it doesn't works.
I am using a bootstrap datepicker. when i click on the icon date& time automatically enters into the input. but the input remained as invalid since i did not interacted with it directly. has any one faced this problem.
here is the plnkr for that: http://plnkr.co/edit/yBmwZCCPvTOQWE6q3BW5
view
<body data-ng-controller="ReservationController as resvnCtrl">
<div class="container">
<div class="col-lg-6 col-lg-offset-3 col-md-8 col-md-offset-2 col-sm-12 col-xs-12 ">
<div>
<h2 class="text-center page-heading">Make a reservation</h2>
</div>
<div>
<form role="form" name="resvnCtrl.form" data-ng-submit="resvnCtrl.submitForm(resvnCtrl.form.$valid)" novalidate>
<div class="form-group" data-ng-class="{'has-error':resvnCtrl.form.time.$invalid && (resvnCtrl.form.time.$dirty || resvnCtrl.form.$submitted) }">
<label class="control-label">Date-Time</label>
<div class='input-group date' id='datetimepicker'>
<input type="text" name="time" id="time" data-ng-model="resvnCtrl.reservation.time"
placeholder="Enter Desired Time" class="form-control" required>
<span class="input-group-addon pointer" data-date-picker>
<i class="fa fa-calendar"></i>
</span>
</div>
<div data-ng-messages="resvnCtrl.form.time.$error" data-ng-if="resvnCtrl.form.time.$dirty || resvnCtrl.form.$submitted">
<p class="help-block" data-ng-message="required">Date and Time required</p>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<input type="submit" name="submit" id="submit" value="Make Reservation" class="btn btn-primary btn-block " >
</div>
</div>
</form>
</div>
</div>
</div>
</body>
controller
var app = angular.module('plunker', []);
angular.module('plunker')
.controller('ReservationController',ReservationController);
ReservationController.$inject=['$scope'];
function ReservationController($scope) {
var resvnCtrl=this;
resvnCtrl.reservation={};
resvnCtrl.confirmation={};
$('#datetimepicker').datetimepicker();
resvnCtrl.submitForm=function(isValid){
alert("valid:"+resvnCtrl.form.time.$valid);
}
}
I think you can refer to angular-strap:http://mgcrea.github.io/angular-strap/#/datepickers. when you import angular-strap.min.js, angular-strap.tpl.min.js and libs.min.css to your index.html. your app.js should be like this:
var app = angular.module('plunker', ['mgcrea.ngStrap.datepicker']);
That's the curse of usage jQuery within angular. Your models controller updates only $viewValue when plugin initialized and that does not trigger digest. Digest triggered my another action - focus in or out that is run digest.
Solution for this is watcher that will manually set $modelValue by $setViewValue() method so angular will know something happened and update validation.
And please, create separate directive for datepicker that will initialize it on element you used directive on.
I have a simple page with 2 fields. I enter the goal name and the use tab to navigate to the next field and then hit the down arrow key to select the Public Group value and when I click the save button, the value of the picklist is setting to Individual which is incorrect. I am not exactly sure how to make the $scope variable pick the updated value from the dropdown
Here's the fiddle
<div ng-app>
<div class="container" ng-controller="goalCtrl">
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">New Record</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-4">
<div class="form-group">
<label for="goalName" class="control-label">Name</label>
<input type="text" class="form-control" id="goalName" placeholder="Goal Name" ng-model="goalie__goal__c.Name">
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label for="fulfilment" class="control-label">Fulfilment</label>
<select class="form-control" id="fulfilment" ng-model="goalie__goal__c.goalie__Fulfilment__c">
<option selected>Individual</option>
<option>Public Group</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<center>
<button class="btn btn-success" ng-click="save()"> Save and add critera</button>
<button class="btn btn-danger" ng-click="cancel()">Cancel</button>
</center>
</div>
</div>
</div>
</div>
</div>
</div></div>
Controller
function goalCtrl($scope) {
$scope.save = function() {
alert(JSON.stringify($scope.goalie__goal__c));
}
}
Update
I updated the controller where I am setting the value to Individual explicitly and then when I hit the save button all the values are updated correctly in the $scope. Not sure why its not working it the initial case.
function goalCtrl($scope) {
$scope.goalie__goal__c = {};
$scope.goalie__goal__c.goalie__Fulfilment__c = 'Individual';
$scope.save = function() {
alert(JSON.stringify($scope.goalie__goal__c));
}
}
I have a simple modal, which contains a form in it. The 'Ok' button should handle success and close the modal whereas the cancel button should just dismiss the modal. If I put the 'Ok' button inside the form tag, the modal instance is shown as undefined in the handler. I need to put the button inside the form for 2 reasons: Design perspective and for ng-submit to work. What could be the issue? Here is the very basic code:
//Modal:
<div class="modal-header">
<h3 class="modal-title">My modal</h3>
</div>
<div class="modal-body">
<form name="modalForm" id="modal-form" class="form-horizontal" role="form" ng-submit="modalOk()" novalidate>
<div class="form-group">
<label class="col-xs-2 control-label">Sample</label>
<div class="col-xs-8" ng-class="{'has-error': modalForm.command.$error.required}">
<input name="command" class="form-control" ng-model="formData.command" maxlength="65" ng-trim="false" required>
</div>
<div class="col-xs-2">
<!-- Modal undefined -- >
<button id="modal-ok" class="btn btn-primary" ng-click="modalOk()" ng-disabled="modalForm.$invalid">Run</button>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<!-- Works here-->
<button id="modal-ok" class="btn btn-primary" ng-click="modalOk()" ng-disabled="modalForm.$invalid">Run</button>
<button class="btn btn-primary site-btn-form" ng-click="modalCancel()">Close</button>
</div>
//Controller code
//.....
$scope.myModal = {};
$scope.launchModal = function() {
//Create a modal for saving the filter
$scope.myModal = $modal.open({
templateUrl : 'views/dialogs/myModal.html',
scope : $scope,
backdrop : 'static'
});
//Save
$scope.modalOk = function() {
//myModal undefined if called from inside the form
$scope.myModal.close();
};
//Cancel the operation
$scope.modalCancel = function() {
$scope.myModal.dismiss();
};
//Handle the modal promise
$scope.myModal.result.then(function() {
console.log('Ok');
}, function() {
console.log('Cancel');
})['finally'](function(){
$scope.myModal = undefined; // Something I tried!
});
};
Any help is appreciated!
You are getting undefined because the modelOk() function is running twice because its also called on ng-submit:
<form name="modalForm" id="modal-form" class="form-horizontal" role="form" ng-submit="modalOk()" novalidate>
You can test this by putting a console.log inside your modalOk() function before the close call.
var app = angular.module('app', ['ui.bootstrap']);
app.controller('myController', function($scope, $modal) {
$scope.myModal = {};
$scope.launchModal = function(num) {
//Create a modal for saving the filter
$scope.myModal = $modal.open({
templateUrl: 'm' + num + '.html',
scope: $scope,
backdrop: 'static'
});
//Save
$scope.modalOk = function() {
console.log("modalOk called");
//myModal undefined if called from inside the form
$scope.myModal.close();
};
//Cancel the operation
$scope.modalCancel = function() {
$scope.myModal.dismiss();
};
//Handle the modal promise
$scope.myModal.result.then(function() {
console.log('Ok');
}, function() {
console.log('Cancel');
})['finally'](function() {
$scope.myModal = undefined; // Something I tried!
});
};
});
<html ng-app='app'>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.min.js"></script>
</head>
<body>
<div ng-controller='myController'>
<button ng-click="launchModal(1)">modal1</button>
<button ng-click="launchModal(2)">modal2</button>
</div>
</body>
<script type="text/ng-template" id="m1.html">
<div class="modal-header">
<h3 class="modal-title">My modal</h3>
</div>
<div class="modal-body">
<form name="modalForm" id="modal-form" class="form-horizontal" ng-submit="modalOk()" role="form" novalidate>
<div class="form-group">
<label class="col-xs-2 control-label">Sample</label>
<div class="col-xs-8" ng-class="{'has-error': modalForm.command.$error.required}">
<input name="command" class="form-control" ng-model="formData.command" maxlength="65" ng-trim="false" required>
</div>
<div class="col-xs-2">
<button id="modal-ok" class="btn btn-primary" ng-click="modalOk()" ng-disabled="modalForm.$invalid">Run</button>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary site-btn-form" ng-click="modalCancel()">Close</button>
</div>
</script>
<script type="text/ng-template" id="m2.html">
<div class="modal-header">
<h3 class="modal-title">My modal</h3>
</div>
<div class="modal-body">
<form name="modalForm" id="modal-form" class="form-horizontal" role="form" novalidate>
<div class="form-group">
<label class="col-xs-2 control-label">Sample</label>
<div class="col-xs-8" ng-class="{'has-error': modalForm.command.$error.required}">
<input name="command" class="form-control" ng-model="formData.command" maxlength="65" ng-trim="false" required>
</div>
<div class="col-xs-2">
<button id="modal-ok" class="btn btn-primary" ng-click="modalOk()" ng-disabled="modalForm.$invalid">Run</button>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary site-btn-form" ng-click="modalCancel()">Close</button>
</div>
</script>
</html>