Currently, I am using a server side framework CakePHP to build my app.
I need to integrate angular into my app.
Currently, I send the following inputs
User.old_password, User.new_password, User.new_password_confirm
to this url /mypasswords/new using POST
This works just fine.
I understand that to send data to server side I need to use services in Angular.
This is my Angular code so far.
var app = angular.module("myApp", []);
app.controller('passwordController', ['$scope', function($scope) {
$scope.submitted = false;
$scope.changePasswordForm = function() {
if ($scope.change_password_form.$valid) {
// Submit as normal
} else {
$scope.change_password_form.submitted = true;
}
}
}]);
services = angular.module('myApp.services', ['ngResource']);
services.factory("UserService", function($http, $q) {
var service;
// service code here
});
So what do I write in the //service code here part? What other parts am I missing?
My form currently looks like this as html after being rendered. (I know I probably have to remove action and method attributes from my form. Do I?)
<form action="/mypasswords/new" id="change_password_form" name="change_password_form" ng-controller="passwordController" ng-submit="changePasswordForm()" method="post" accept-charset="utf-8" class="ng-scope ng-pristine ng-valid">
<div style="display:none;"><input type="hidden" name="_method" value="POST"></div>
<input name="data[User][old_password]" id="u56" placeholder="Enter old password..." class="u56 profile_input" type="password">
<input name="data[User][new_password]" id="u57" placeholder="Enter new password..." class="u57 profile_input" type="password">
<input name="data[User][new_password_confirm]" id="u58" placeholder="Enter new password..." class="u58 profile_input" type="password">
<div id="u25" class="u25_container">
<div id="u25_img" class="clear_all_button detectCanvas" onclick="document.getElementById('change_password_form').reset()">
</div>
</div>
<div id="u27" class="u27_container">
<input id="u27_img" class="submit_button detectCanvas" type="submit" value="SAVE">
</div>
</form>
Thank you.
if you want just to send the form with ajax, No need to create factory, just do it in controller like this:
var app = angular.module("myApp", [$http]);
app.controller('passwordController', ['$scope', function($scope) {
$scope.submitted = false;
$scope.changePasswordForm = function() {
if ($scope.change_password_form.$valid) {
//note: use full url, not partial....
$http.post('http://myweb.com/mypasswords/new', change_password_form.Data)
.success(function(data, status, headers, config) {
//do anything when it success..
})
.error(function(data, status, headers, config){
//do anything when errors...
});
} else {
$scope.change_password_form.submitted = true;
}
}
}]);
And your form will looks like this:
<form id="change_password_form" name="change_password_form" ng-controller="passwordController" ng-submit="changePasswordForm()" method="post" accept-charset="utf-8" class="ng-scope ng-pristine ng-valid">
<div style="display:none;"><input type="hidden" name="_method" value="POST"></div>
<input name="data[User][old_password]" ng-model="Data.old_password" id="u56" placeholder="Enter old password..." class="u56 profile_input" type="password">
<input name="data[User][new_password]" ng-model="Data.new_password" id="u57" placeholder="Enter new password..." class="u57 profile_input" type="password">
<input name="data[User][new_password_confirm]" ng-model="Data.new_password_confirm" id="u58" placeholder="Enter new password..." class="u58 profile_input" type="password">
<div id="u25" class="u25_container">
<div id="u25_img" class="clear_all_button detectCanvas" onclick="document.getElementById('change_password_form').reset()">
</div>
</div>
<div id="u27" class="u27_container">
<input id="u27_img" class="submit_button detectCanvas" type="submit" value="SAVE">
</div>
</form>
Step 1: write form using normal html instead of FormHelper in CakePHP
The form should look like this:
<form name="change_password_form" ng-controller="passwordController"
ng-submit="changePasswordForm()">
<input name="data[User][old_password]" ng-model="data.User.old_password" type="password" placeholder="Enter old password..." class="u56 profile_input">
<input name="data[User][new_password]" ng-model="data.User.new_password" type="password" placeholder="Enter new password..." class="u57 profile_input">
<input name="data[User][new_password_confirm]" ng-model="data.User.new_password_confirm" type="password" placeholder="Enter new password again..." class="u58 profile_input">
<div id="u25"
class="u25_container">
<div id="u25_img"
class="clear_all_button detectCanvas" onclick="document.getElementById('change_password_form').reset()">
</div>
</div>
<div id="u27"
class="u27_container">
<button type="submit" id="u27_img" ng-click="debug()"
class="submit_button detectCanvas" />
</div>
</form>
Step 2: write the app.js in the following manner.
the X-Requested-With header is important if you want to use the CakePHP $this->request->is('ajax')
angular.module("myApp", [])
.controller('passwordController', function($scope, $http) {
$scope.changePasswordForm = function() {
console.log('change passwrd form activated');
//note: use full url, not partial....
$http({
method : 'POST',
url : '/mypasswords/new',
data : $.param($scope.data), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With' : 'XMLHttpRequest'
} // set the headers so angular passing info as form data (not request payload)
})
.success(function(data, status, headers, config) {
//do anything when it success..
console.log('works!');
})
.error(function(data, status, headers, config){
//do anything when errors...
console.log('errors!');
});
}
$scope.debug = function () {
console.log($scope);
}
});
Related
I built a sign up from using angularjs. The submitting process is OK. Then I want to make a validation of checking if the email is already registered. If exist, show the error message informing that the email exists. The problem I face is when user changes the email address, the submitted email is still the previous one. How to tell angular that the input value has changed and submit the newly inserted values.
My sign up form
<div ng-controller="signupController">
<form ng-submit="doSignup()">
<h2 class="form-signin-heading">Sign Up</h2>
<div class="login-wrap">
<input type="text" name="email" class="form-control" autofocus="" ng-model="formData.email">
<span class="text-danger">{{ emailExistError }}</span>
<input type="password" name="password" class="form-control" placeholder="Password" ng-model="formData.password">
<input type="password" name="password_conf" class="form-control" placeholder="">
<button class="btn btn-lg btn-login btn-block" type="submit">Sign Up</button>
</div>
</form>
</div>
The app.js
angular.module('myApp', ['ngRoute', 'ngSanitize'])
.controller('mainController', function ($scope, $http) {
})
.controller('signupController', function ($scope, $http,$window) {
$scope.formData = {};
$scope.doSignup = function () {
$http({
method: 'post',
url: 'signup.php',
data: $.param($scope.formData),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function (data) {
$scope.login = data;
if (data.status == 'ok') {
$('#successModal').modal('show');
}
else if (data.status == 'email exist'){
$scope.emailExistError = 'Email exist. Use different email';
}
else {
$('#failedModal').modal('show');
}
})
}
})
try
$watch('email',function(newVal,oldVal){
if(newVal!=oldVal){
$scope.doSignup();
}});
It's maybe a stupid question but it's late and i'm desperate.
I have a angularjs application that uses ngRoute. But everything is done in one controller. Now I have a form in a view and the use of that form is to put it's input field data into a var to send with post.
Don't mind al the console log i'm trying to find the error.
APP.JS
`
$scope.addDevice = function(){
$scope.device = {};
var data = {
'Name' : $scope.device.ChildName,
'Serial' : $scope.device.Serial
};
console.log($scope.device.Serial);
console.log($scope.device.ChildName);
console.log(data);
$http.post('http://141.135.5.117:3500/device/register', data, { headers: headers })
.then(function(response){
console.log(response);
console.log(headers);
});
}`
Settings.html ( Note: this is a view in ng-view)
<form role="form" class='userForm'>
<label for="addDevice">Add Device</label>
<input type="text" class="form-control" id="deviceserial" placeholder="Enter serial number" ng-model="$scope.device.Serial">
<input type="text" class="form-control" id="Devicechildname" placeholder="Enter baby name" ng-model="$scope.device.ChildName">
<button type="submit" class="btn btn-success btn-block" ng-click="addDevice()">Add Device</button>
<p>{{$scope.device.Serial}}</p>
</form>
This is the console output
Console output
All the functions are done in one controller.
First Remove $scope from ng-model="$scope.device.Serial"
and define $scope.device = {}; outside $scope.addDevice = function(){
$scope.device = {};
$scope.addDevice = function(){
-- you code here --
}
Working code example
angular.module('inputExample', [])
.controller('ExampleController', ['$scope','$http', function($scope,$http) {
$scope.val = '1';
$scope.device = {};
$scope.addDevice = function(){
var data = {
'Name' : $scope.device.ChildName,
'Serial' : $scope.device.Serial
};
console.log($scope.device.Serial);
console.log($scope.device.ChildName);
console.log(data);
$http.post('http://141.135.5.117:3500/device/register', data)
.then(function(response){
console.log(response);
console.log(headers);
});
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="inputExample">
<div ng-controller="ExampleController">
<form role="form" class='userForm'>
<label for="addDevice">Add Device</label>
<input type="text" class="form-control" id="deviceserial" placeholder="Enter serial number" ng-model="device.Serial">
<input type="text" class="form-control" id="Devicechildname" placeholder="Enter baby name" ng-model="device.ChildName">
<button type="submit" class="btn btn-success btn-block" ng-click="addDevice()">Add Device</button>
<p>{{device.Serial}}</p>
</form>
</div>
</div>
I have recently started working on AngularJS 1.6.
I am trying to submit a form programmatically. The reason is I want to validate a few fields (required field validation). I have spent a lot of efforts (probably 3-4 hours) trying to make this work but none of the existing answers on stack overflow or AngularJS docs seems to be working for me today (strange), hence I am posting this as last resort.
Below is my html
<form method="post" id="loginform" name="loginform" ng-submit="loginUser()" novalidate>
<div>
{{message}}
</div>
<div>
<label>User Name</label>
<input type="text" id="txtUserName" ng-model="user.UserName" name="user.UserName" />
</div>
<div>
<label>Password</label>
<input type="text" id="txtPassword" ng-model="user.Password" name="user.Password" />
</div>
<div>
<input type="submit" id="btnLogin" title="Save" name="btnLogin" value="Login" />
</div>
</form>
My angular code
var demoApp = angular.module('demoApp', []);
demoApp.controller("homeController", ["$scope", "$timeout", function ($scope, $timeout) {
$scope.loginUser = function () {
var form = document.getElementById("loginform");
//var form = $scope.loginform; - tried this here...
//var form = $scope["#loginform"]; tried this
//var form = angular.element(event.target); - tried this...
// tried a lot of other combinations as well...
form.attr("method", "post");
form.attr("action", "Home/Index");
form.append("UserName", $scope.user.UserName);
form.append("Password", $scope.user.Password);
form.append("RememberMe", false);
form.submit();
};
}]);
I keep on getting error 'attr' is not a function.
All I need is submit a form using post method, with values. Just before that I am trying to intercept the submit call and check for validations.
I am open to try any other approach as well. Such as changing the input type from submit to button. Putting the input outside the form. I would be more than happy if validations and submit both can happen any which way. I just want it to post back the values after validating on the client side and then the server will take care of the redirect.
Note: I want the form to do a full postback so that I can get it to redirect to another form. (I know I could use Ajax, but some other day, may be!)
1st of all avoid doing var form = document.getElementById("loginform");. Instead of using form.submit you can use the following code. Do it the angular way cheers :D
$scope.loginUser = function () {
if($scope.loginform.$valid){
user.rememberme=false;
$http({
url: 'Home/Index',
method: "POST",
data: user
})
.then(function(response) {
// success
},
function(response) { // optional
// failed
});
}
};
this is a code to validation if validation not complate button is not enable
<form method="post" id="loginform" name="loginform" ng-submit="loginUser()" novalidate>
<div>
{{message}}
</div>
<div>
<label>User Name</label>
<input type="text" id="txtUserName" required ng-model="user.UserName" name="UserName" />
</div>
<div>
<label>Password</label>
<input type="text" id="txtPassword" ng-model="Password" name="user.Password"required />
</div>
<div>
<input type="submit" ng-disabled="myForm.UserName.$invalid || myForm.Password.$invalid" id="btnLogin" title="Save" name="btnLogin" value="Login" />
</div>
</form>
You should use $scope when trying to access the form, something like $scope.loginform. But......
Take a look at ng-messages. Heres an example using ng-messages with your form:
<form id="loginform" name="loginform" ng-submit="loginUser()">
<div>
{{message}}
</div>
<div>
<label>User Name</label>
<input type="text" id="txtUserName" ng-model="user.UserName" name="user.UserName" required/>
<div class="help-block" ng-messages="loginform.txtUserName.$error" ng-show="loginform.txtUserName.$touched">
<p ng-message="required">Username is required.</p>
</div>
</div>
<div>
<label>Password</label>
<input type="text" id="txtPassword" ng-model="user.Password" name="user.Password" required/>
<div class="help-block" ng-messages="loginform.txtPassword.$error" ng-show="loginform.txtPassword.$touched">
<p ng-message="required">Password is required.</p>
</div>
</div>
<div>
<input type="submit" id="btnLogin" title="Save" name="btnLogin" value="Login" ng-click="loginUser()" />
</div>
</form>
Add ngMessages:
var demoApp = angular.module('demoApp', ['ngMessages']);
demoApp.controller("homeController", ["$scope", "$timeout", function ($scope, $timeout) {
$scope.loginUser = function () {
if($scope.loginform.$valid){
//Code to run before submitting (but not validation checks)
} else{
return false;
}
};
}]);
Don't forget to include ngMessages in your app declaration and include the ngMessages.js script file. Note how you can simply use HTML5 validators.
I found the thing I was looking for. In the end I had to create a directive for validating and then submitting. So I am posting it here as a whole answer.
My HTML
<div ng-controller="homeController" ng-init="construct()">
<form method="post" action="Index" role="form" id="loginform" name="loginform" ng-form-commit novalidate class="ng-pristine ng-invalid ng-invalid-required">
<div class="form-group">
<label for="UserName">User ID</label>
<input autocomplete="off" class="form-control ng-valid ng-touched ng-pristine ng-untouched ng-not-empty"
id="UserName" name="UserName" ng-model="user.UserName" type="text" value=""
ng-change="userNameValidation = user.UserName.length == 0">
<span class="field-validation-error text-danger" ng-show="userNameValidation">The User ID field is required.</span>
</div>
<div class="form-group">
<label for="Password">Password</label>
<input autocomplete="off" class="form-control ng-valid ng-touched ng-pristine ng-untouched ng-not-empty"
id="Password" name="Password" ng-model="user.Password" type="password" value=""
ng-change="passwordValidation = user.Password.length == 0">
<span class="field-validation-error text-danger" ng-show="passwordValidation">The Password field is required.</span>
</div>
<div>
<input type="button" id="btnLogin" title="Login" name="btnLogin" value="Login" ng-click="validateUser(loginform)" />
</div>
</form>
</div>
Look for ng-form-commit on the form element. It is the directive that I created.
My Angular code
var demoApp = angular.module('demoApp', []);
demoApp.factory("commonService", function () {
return {
isNullOrEmptyOrUndefined: function (value) {
return !value;
}
};
});
//This is the directive that helps posting the form back...
demoApp.directive("ngFormCommit", [function () {
return {
require: "form",
link: function ($scope, $el, $attr, $form) {
$form.commit = function () {
$el[0].submit();
};
}
};
}]);
demoApp.controller("homeController", ["$scope", "commonService", function ($scope, commonService) {
$scope.construct = function construct() {
$scope.user = { UserName: "", Password: "" };
};
$scope.userNameValidation = false;
$scope.passwordValidation = false;
$scope.isFormValid = false;
$scope.validateUser = function ($form) {
$scope.isFormValid = true;
$scope.userNameValidation = commonService.isNullOrEmptyOrUndefined($scope.user.UserName);
$scope.passwordValidation = commonService.isNullOrEmptyOrUndefined($scope.user.Password);
$scope.isFormValid = !($scope.userNameValidation || $scope.passwordValidation);
if ($scope.isFormValid === true) {
$scope.loginUser($form);
}
};
$scope.loginUser = function ($form) {
$form.commit();
};
}]);
I found the directive here
Example using Angular 1.5 components.
(function(angular) {
'use strict';
function DemoFormCtrl($timeout, $sce) {
var ctrl = this;
this.$onInit = function() {
this.url = $sce.trustAsResourceUrl(this.url);
/*$timeout(function() {
ctrl.form.$$element[0].submit();
});*/
};
this.validate = function(ev) {
console.log('Running validation.');
if (!this.form) {
return false;
}
};
}
angular.module('app', [])
.component('demoForm', {
template: `
<p>To run this demo allow pop-ups from https://plnkr.co</p>
<hr>
<p>AngularJS - submit form programmatically after validation</p>
<form name="$ctrl.form" method="get" target="blank" action="{{::$ctrl.url}}" novalidate
ng-submit="$ctrl.validate($event)">
<input type='hidden' name='q' ng-value='::$ctrl.value'>
<input type='hidden' name='oq' ng-value='::$ctrl.value'>
<input type="submit" value="submit...">
</form>`,
controller: DemoFormCtrl,
bindings: {
url: '<',
value: '<'
}
});
})(window.angular);
https://plnkr.co/edit/rrruj6vlWrxpN3od9YAj?p=preview
I'm having trouble with this simple form: My lack of javascript is holding me back!
If anyone can give me some pointers: I have been unable to find documentation (non-php), which I understand, and gives a full overview of connecting the form data to the '$http' service.
(I'm not getting errors however the data is not registering with the server.)
data format:
{"item_name":"Contact Me Form", "item_data":{"Name":"John Smith", "Email":"john#smith.com", "PhoneNumber":"222-333-4444"}}
script:
angular.module('formApp', [])
.controller('FormController', ['$scope', '$http', function($scope, $http) {
$scope.form_data = {};
$scope.update = function(user) {
$scope.form_data = angular.copy(user);
var dataObject = {
item_name : "Contact Me Form"
,item_data : $scope.form_data
};
var responsePromise = $http.post("http://server-url", dataObject, {});
responsePromise.success(function(dataFromServer, status, headers, config)
{
var outputDate=angular.fromJson(dataFromServer);
});
responsePromise.error(function(data, status, headers, config) {
console.log("Error in fetching user store call!");
});
};
}]);
<div ng-app="formApp">
<div ng-controller="FormController">
<form novalidate class="animated" >
<input
type="text"
ng-model="user.Name"
class="form-control"
id="Name"
placeholder="Your Name" required /><br />
<input
type="email"
ng-model="user.Email"
class="form-control "
id="Email"
placeholder="Company Email" required/><br />
<input
type="text" ng-model="user.PhoneNumber"
class="form-control "
id="Number"
placeholder="Phone - (optional)" /><br />
<input
id="submit"
class="btn-default btn-lg " type="submit"
ng-click="update(user)"
value="Save"
/>
</form>
</div>
</div>
I am implementing AngularJS on an existing web application that requires a common HTTP POST like you would do without AngularJS.
Does any one have a work around to do that?
i have tried setting action="#" and action="." and just action and then do some jquery to inject a action like this. but nothing works
<script type="text/javascript">
$("form").get(0).setAttribute( "action", "test.html" );
</script>
HERE IS MY FORM AND CODE
//MY FORM
<form name="userForm" ng-submit="submitForm(userForm.$valid)" xt-form novalidate>
<div class="form-group">
<div class="col-sm-6" ng-class="{ 'has-error' : userForm.fornavn.$invalid && !userForm.fornavn.$pristine }">
<label class="control-label" for="textinput">Fornavn <span class="star-color">*</span></label>
<input autocomplete="off" type="text" value="<?php echo set_value('fornavn'); ?>" name="fornavn" ng-model="userFormData.fornavn" class="form-control" xt-validate msg-required="Du skal udfylde dit Fornavn" required>
</div>
<div class="col-sm-6" ng-class="{ 'has-error' : userForm.efternavn.$invalid && !userForm.efternavn.$pristine }">
<label class=" control-label" for="textinput">Efternavn <span class="star-color">*</span></label>
<input autocomplete="off" type="text" value="<?php echo set_value('efternavn'); ?>" name="efternavn" ng-model="userFormData.efternavn" class="form-control" xt-validate msg-required="Du skal udfylde dit Efternavn" required>
</div>
</div>
<button id="membership-box__payBtn" type="submit" ng-model="userFormData.betaling" name="betaling" class="btn btn-success text-uppercase">Gå til betaling</button>
</form>
//CODEIGNITER CONTROLLER
if (isset($_POST['betaling'])) {
$data['tilBetaling'] = array(
'oprettelse' => $this->input->post('oprettelse'),
// 'medlemskab' => $this->input->post('medlemskab'),
'tilBetaling' => str_replace(',', '.', $this->input->post('tilBetaling')),
'pr_maaned' => $this->input->post('pr_maaned'),
'start_date' => $this->input->post('start_date'),
'til_dato' => $this->input->post('til_dato'),
'pakke' => $this->input->post('pakke'),
'type' => $this->input->post('medlemskabTypeFinal'),
'getCenter' => $this->input->post('getCenter'),
'medlemskabPakkePID'=> $this->input->post('medlemskabPakkePID'),
'ekstraInput' => $this->input->post('ekstraInput'),
'periode_price' => $this->input->post('periode_price'),
'kampagneTag' => $this->input->post('kampagneTag'),
// 'header' => $this->input->post('header'),
);
//Gem array til session
$_SESSION['betaling'] = $data['tilBetaling'];
}
If you want to do a normal submit, you can handle ngClick in your controller:
HTML
<div ng-controller="ctrl">
<form name="userForm" action="user/add" method="post">
Name: <input name="name" ng-model="user.name" />
...
<button ng-click="onSubmit(userForm)">Submit</button>
</form>
</div>
JS
app.controller('ctrl', function($scope) {
$scope.onSubmit = function(form) {
if (form.$valid) {
var e = document.getElementsByName(form.$name);
e[0].submit();
}
}
});
An Alternative Solution
As an alternative, consider leveraging services, and redirecting after a successful POST in AngularJS.
HTML
<div ng-controller="ctrl">
<form name="userForm" ng-submit="onSubmit(user)">
Name: <input name="name" ng-model="user.name" />
...
<button type="submit">Submit</button>
</form>
</div>
JS
app.factory('UserService', function($http) {
return {
addUser: function(user) {
return $http({method:'POST', url:'api/user/add', data: user });
}
}
});
app.controller('ctrl', function($scope, $location, UserService) {
$scope.onSubmit = function(user) {
if ($scope.userForm.$valid) {
UserService.addUser(user).success(function() {
$location.path('/user/addSuccessful')
});
}
}
});
Even if you do an AngularJs submit, the request does not go to server. The control still remains on client side. Then you can post the data/form etc through $http service. You can inject $http service in your controller. as
app.controller('reviewCtrl', ['$http', function($http){
$scope.addReview = function(product){
//use $http service here
// Simple POST request example (passing data) :
$http.post(' / someUrl ', {msg:' hello word!'}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
}]);
note: please review the syntax before running the code.
To submit the Angular Js form ONLY after Angular validations are through or passed, you must use reviewForm.$valid flag chack in ng-submit.
With this flag check, the form will not get submitted until all validations are passed.
<form name="reviewForm" ng-controller="reviewCtrl" ng-submit="reviewForm.$valid && reviewCtrl.addReview(product)" novalidate>
....
....
</form>