I came across a situation where I need to call server method before continue with the FORM POST in angularJS. If the server method returns an error I need to display it and remain in the same method which ultimately does not do the POST request.
How can I achieve this with AngularJS?
See my code sample below
HTML
<form action="http://app.test.com/ProcessTransaction" method="POST">
<table>
<tr>
<td><input type="hidden" name="Amount" value="25.00" /></td>
</tr>
<tr>
<td><input type="hidden" name="Currency" value="NZD" /></td>
</tr>
</table>
<div class="container-fluid align:left">
<button type="submit" class="btn btn-success" ng-disabled="properties.disabled" ng-click="ctrl.action()">{{properties.label}}</button>
</div>
</form>
Angular Controller
this.action = function action() {
var req = {
method: method,
url: <some_url>,
data: angular.copy(data_to_sent),
params: params
};
return $http(req)
.success(function(data, status) {
$scope.properties.dataFromSuccess = data;
})
.error(function(data, status) {
$scope.properties.dataFromError = data;
})
.finally(function() {
});
}
Okay based on the question OP want's to validate the form and then go for submitting the form values.There are two approaches here
1) Do the form validation on client side using <ng-form> / <form> and required in the input fields.
2) We can skip the traditional way of form submit and just call our submit function on submit click and validate the form from server and if it's success then go for saving the form value or else display errors.
Make below changes for approach (2) as it will be closest for you question.
In HTML
<form>
<table>
<tr>
<td><input type="hidden" name="Amount" value="25.00" /></td>
</tr>
<tr>
<td><input type="hidden" name="Currency" value="NZD" /></td>
</tr>
</table>
<div class="container-fluid align:left">
<button type="submit" class="btn btn-success" ng-disabled="properties.disabled" ng-click="ctrl.action()">{{properties.label}}</button>
</div>
</form>
In JS
this.action = function action() {
var req = {
method: method,
url: <some_url>,
data: angular.copy(data_to_sent),
params: params
};
return $http(req)
.success(function(data, status) {
$scope.properties.dataFromSuccess = data;//here data can contain whether the form is valid or invalid...so create a boolean at server if it's valid or not..
if($scope.properties.dataFromSuccess.isSuccess){
$http.post(URL,formData).success(function(data){
$scope.dataSaved = data;
});
}else{
$scope.properties.dataFromError = data; //set the errors in the scope to display
}
})
.error(function(data, status) { //this error means request has been failed to process not the validation error we are checking at server..
//$scope.properties.dataFromError = data;
})
.finally(function() {
});
}
Related
When my scope has two properties that each contain an array retrieved asynchronously from the database, I cannot elegantly access the one from the other. I'm sure I must be missing something because my current solution feels like a hack.
I have an Angular CRUD page that contains a table and a form which contains a dropdown select control. When I click on a row in the table and want to update it, I need to populate the dropdown with the current value. In order to get this right, I'm currently declaring a global variable and assign the array used to populate the dropdown to that variable once it is retrieved from the database.
var columnHeaderArray;
var app = angular.module('myApp', []);
app.controller('ColumnHeadingController',
function ($scope, $http) {
$scope.GetAllData = function () {
$http({
method: "get",
url: "/api/Staat8Maintenance/GetAllColumnHeadings"
}).then(function (response) {
$scope.columnheaders = response.data;
$scope.GetGroupHeaderData();
},
function () { alert("Error Occured"); });
};
$scope.GetGroupHeaderData = function () {
$http({
method: "get",
url: "/api/Staat8Maintenance/GetGroupHeadingsForCombo"
}).then(function (response) {
$scope.groupheaders = response.data;
columnHeaderArray = response.data;
},
function () { alert("Error Occured"); });
};
$scope.UpdateColumnHeading = function (cho) {
document.getElementById("OriginalOrder").innerHTML = cho.ColumnOrder;
document.getElementById("OriginalColumnHeading").innerHTML = cho.ColumnHeading;
$scope.ColumnHeading = cho.ColumnHeading;
$scope.ColumnOrder = cho.ColumnOrder;
$scope.SelectedOption = columnHeaderArray[columnHeaderArray.findIndex(x => x.GroupingHeaderId == cho.GroupingHeaderId)];
document.getElementById("btnSave").setAttribute("value", "Update");
document.getElementById("btnSave").style.backgroundColor = "Yellow";
document.getElementById("formColumnHeading").style.display = "block";
};
}
);
<div id="SubAccountGrouping" class="tabcontent"
ng-controller="ColumnHeadingController"
ng-init="GetAllData()">
<h2>Column Headings</h2>
<h5>This is where the column headings will be maintained.</h5>
<div id="formColumnHeading" class="form" role="form">
<div class="container">
<div class="row">
<div class="form-horizontal">
<div class="form-group">
<label class="col-sm-1 edittextwide">Heading:</label>
<div class="col-sm-6">
<input type="text" class="form-control edittextwide"
id="inputColumnHeading"
placeholder="Column Heading"
ng-model="ColumnHeading" />
</div>
</div>
<div class="form-group">
<label class="col-sm-1">Order:</label>
<div class="col-sm-6">
<input type="number" class="form-control"
id="inputColumnOrder"
placeholder="Order"
ng-model="ColumnOrder" />
</div>
</div>
<div class="form-group">
<label class="col-sm-1 edittextwide">Group Heading:</label>
<div class="col-sm-6">
<select class="form-control edittextwide"
name="groupHeadings"
id="selectGroupHeadings"
ng-model="SelectedOption"
ng-options="gh as gh.HeadingName for gh in groupheaders track by gh.GroupingHeaderId">
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div>
<input type="button" id="btnSave" class="form-control btn-default"
value="Submit" ng-click="InsertData()" />
</div>
</div>
</div>
<div class="hiddenlabel">
<label id="OriginalOrder">0</label>
<label id="OriginalColumnHeading">ABC</label>
</div>
</div>
<div class="scrolldiv">
<table class="table">
<thead>
<tr>
<th>Heading</th>
<th>No of Sub-Accounts</th>
<th>Column Order</th>
<th>Group Heading</th>
<th>Parent Group Heading</th>
<th>Include in Staat 8</th>
<th>Actions</th>
</tr>
</thead>
<tr ng-repeat="cho in columnheaders">
<td>{{cho.ColumnHeading}}
</td>
<td>{{cho.NumberOfEntries}}
</td>
<td>{{cho.ColumnOrder}}
</td>
<td>{{cho.GroupHeading}}
</td>
<td>{{cho.ParentGroupHeading}}
</td>
<td>{{cho.IncludeInStaat8?'Yes':'No'}}
</td>
<td>
<input type="button" class="btn btn-warning"
value="Update"
ng-click="UpdateColumnHeading(cho)" />
</td>
</tr>
</table>
</div>
</div>
When I try to set $scope.SelectedOption using $scope.groupheaders directly, it bombs out. I realise this is because of the asynchronous nature, but I suspect there must be a more elegant way to achieve this?
// include $q to use promises
function ($scope, $http, $q) {
// create a deferred promise
var q = q.defer();
// call the first $http method and store the promise
var promise1 = $http(config1);
// call the second $http method and store the promise
var promise2 = $http(config2);
// handle when the first promise resolves
promise1
.then( (data) => {
$scope.columnheaders = response.data;
})
.catch( (errors) => q.reject(errors));
// handle when the second promise resolves
promise2
.then( (data) => {
$scope.groupheaders = response.data;
})
.catch( (errors) => q.reject(errors));
// wait for both promises to resolve then do final actions
$q.all([promise1, promise2])
.then( () => {
columnHeaderArray = response.data;
q.resolve();
});
// return the promise for calling methods to wait until this resolves
return q.promise;
}
Reference for using $q
Reference for using $http
You can streamline the above code to make it more condensed, but I've broken it out some to be a little easier to follow.
I have client list in a table.
When I click on editClient, the name of the client will be displayed in an input text. This work perfectly.
<body ng-app="myClientApp" ng-controller="myClientController">
<a class="btn btn-success" ng-click="chargerClients()">
Charger Clients
</a>
<div ng-if="clients">
<table>
<tr ng-repeat="cl in clients >
<td>{{cl.idClient}} </td>
<td>{{cl.nomClient}} </td>
<td> <a class="btn btn-success" ng-click="editClient(cl.idClient,cl.nomClient)"></td>
</table>
<div>
<input type="text" ng-model="id">
<input type="text" ng-model="nom">
<button ng-click="modifyClient()"> validate</button>
</div>
</div>
</body>
The problem is when I click on modifyClient, it keeps the same values and nothing happens. How can I fix this problem?
<script>
var app=angular.module("myClientApp", []);
app.controller("myClientController", function($scope,$http,$window) {
$scope.chargerClients=function(){
$http.get("/clients")
.success(function(data){
$scope.clients=data;
});
};
//load id and name
$scope.editClient=function(idClient, nomClient){
$scope.id=idClient;
$scope.nom=nomClient;}
//modifyClient
$scope.modifyClient=function(){
var params="";
var params = ({
idClient:$scope.id,
nomClient: $scope.nom});
$http({
method: 'PUT',
url: "clients",
data: params,
headers: {'Content-type': 'application/json'}
})
.success(function(data) {
$window.alert($scope.id+$scope.nom);
$scope.chargerClients();
$window.location.href = '/index.html'
})
};
}
</script>
Try using POST method in your modifyClient
Thank you i solve it; i have to add link in ng-model:
`<ng-model="client.id">`
and in the script also:
$scope.client={}
$scope.editClient=function(idClient, nomClient){
$scope.client.id=idClient;
}
$scope.modifyClient=function(){
var params="";
var params = ({
idClient:$scope.client.id
});
I am trying to get data using REST api from html form using angularjs and do some db operation on it. I am getting 404 error for the rest link specifid.
Here's my js code
var app=angular.module("myApp",[]);
app.controller("mycon",function($scope,$http){
console.log("entered here");
$scope.test={};
$scope.add = function() {
console.log("entered here");
var json=JSON.stringify($scope.test);
console.log($scope.test);
console.log(json);
$http({
url: "rest/xyz/role",
method: "GET",
data: json,
headers: {'Content-Type': 'application/json'}
})
.success(function(data, status,header,config) {
$scope.data = data;
}).error(function(data, status,header,config) {
alert("error");
});
}});
<body ng-app="myApp" ng-controller="mycon">
<center>
<h2> Login Here! </h2>
<hr/>
<form >
<table>
<tr>
<td>Signum Id:</td>
<td><input type="text" ng-model="test.sig"/></td>
</tr>
<tr>
<button class="btn waves-effect waves-light" type="submit" ng-click="add()" name="action"> Submit <i class="material-icons right">send</i>
</tr>
</table>
</form>
</center>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
</body>
and my REST code goes here.
#Path("/xyz")
public class RestServices {
#GET
#Path("/role")
#Produces({ "application/json" })
public String list() {
//do db operation
}
}
After deploying and running the project on server, I am getting following error:
http://localhost:8080/LoginEmployee/rest/xyz/role "404 NOT FOUND".
Add servlet mapping in web.xml as "rest/*". and also check the project name which should be "LoginEmployee"
Try removing rest/ from $http param.
url: "xyz/role",
It works now...
I GET array and stick name in input, then I change name in input and PUT it.
HTML
<form id="edit">
<table>
<tr>
<th>Name: </th>
<td>
<input id="name" form="edit" type="text" ng-model="name" required>
</td>
</tr>
</table>
<button ng-click="edit()">Submit</button>
</form>
AngularJS
$scope.display = function()
{
var connection = $http(
{
method: 'GET',
url: 'http://localhost:8080/students?id=' + $scope.id
})
.then(function(response)
{
$scope.myArray = response.data;
$scope.name = $scope.myArray[0].name;
})
You need to check the status_code on the response not on response.data:
if (response.status == 200)
{
success();
}
else
{
fail();
}
You should check your $scope.name properly update in controller when you hit the button. your request might be fail because of your $scope.name not update in controller properly.
I am using angular for login page but return null parameters to controller.
view page:this my code in view page
<div ng-controller="LoginController">
<form novalidate name="f1" ng-submit="Login()">
<div style="color:rgb(142,2,2)">{{Message}}</div>
<table ng-show="!IsLogedIn">
<!-- Here ng-show="!IsLogedIn" means I want to hide table after loged in-->
<tr>
<td>Username : </td>
<td>
<!-- Here ng-class="Submitted?'ng-dirty':''" Means if submitted (clicked submit button) then make this dirty state
for show red border-->
<input type="text" ng-model="Login.Username" name="cUsername" ng-class="Submitted?'ng-dirty':''" required autofocus />
<span class="error" ng-show="(f1.cUsername.$dirty || Submitted) && f1.cUsername.$error.required">Username required</span>
<!-- ng-show="(f1.cUsername.$dirty || Submitted) && f1.cUsername.$error.required" Means I want to show this span only when
the control cUsername is invalid-->
</td>
</tr>
<tr>
<td>Password : </td>
<td>
<input type="password" ng-model="Login.pass" name="cPassword" ng-class="Submitted?'ng-dirty':''" required autofocus />
<span class="error" ng-show="(f1.cPassword.$dirty || Submitted) && f1.cPassword.$error.required">Password required</span>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Login" />
</td>
</tr>
</table>
</form>
</div>
i need to use the returned value from this factory in other factories.
but get null parametrs
mycontroll.js
angular.module('MyApp')
.controller('LoginController', function ($scope, LoginService) {
$scope.IsLogedIn = false;
$scope.Message = '';
$scope.Submitted = false;
$scope.IsFormValid = false;
$scope.LoginData = {
Username: '',
Password: ''
};
//Check is Form Valid or Not // Here f1 is our form Name
$scope.$watch('f1.$valid', function (newVal) {
$scope.IsFormValid = newVal;
});
$scope.Login = function () {
$scope.Submitted = true;
if ($scope.IsFormValid) {
LoginService.GetUser($scope.LoginData).then(function (d) {
if (d.data.Username != null) {
$scope.IsLogedIn = true;
$scope.Message = "Successfully login done. Welcome " + d.data.Name;
}
else {
alert('Invalid Credential!');
}
});
}
};
})
.factory('LoginService', function ($http) {
var fac = {};
fac.GetUser = function (d) {
return $http({
url: '/login/Login',
method: 'POST',
data: JSON.stringify(d),
headers: { 'content-type': 'application/json' }
});
};
return fac;
});
logincontrol
[HttpPost]
public virtual JsonResult Login(Login d)
{
using (CrudAngularEntities dc = new CrudAngularEntities())
{
var user = dc.Users.Where(a => a.Username.Equals(d.Username) && a.pass.Equals(d.pass)).FirstOrDefault();
return new JsonResult { Data = user, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
}
You are passing $scope.LoginData to the function LoginService.GetUser. The corresponding server model is Login. Hence its signature needs to be same.
$scope.LoginData = {
pass : '',
Username: ''
};
Then you mapped the ng-models to something else (to Login obj). You may need to replace inputs for username and password with
<input type="text" ng-model="LoginData.Username"
<input type="password" ng-model="LoginData.pass"