how to post data to server using angularJS, web api - javascript

i am new to angularJS and trying to figure out, how to post data to my server, problem is that my post to server is successful and it create new record but all is empty(null).
Thanks for any advice
JS:
$scope.addChannel = function () {
var channels = [];
//var newChannel = {
// Name: $scope.Name
//};
//clearing error message
$scope.errorMessage = "";
$http.post("api/Channel/channels", newChannel)
.success(function (newChannel) {
//on success
$scope.channels.push({ "Name": $scope.Name });
console.log("data added");
// newChannel.push(response.data);
newChannel = {};
}, function () {
//on failure
$scope.errorMessage = "Failed to save data";
})
}
HTML:
<div ng-controller="ChannelController">
<div class="col-md-4 col-lg-4 col-sm-4">
<form novalidate name="newUser"ng-submit="addChannel()">
<div class="form-group">
<label for="name">Channel</label>
<input class="form-control" type="text" id="Name" name="Name" ng-model="newChannel.Name" />
</div>
<div class="form-group">
<input type="submit" value="Add" class="btn btn-success" />
</div>
</form>
<a ng-href="/Dashboard#/channels">Return to dashboard</a>
</div>
<div class="has-error" ng-show="errorMessage">
{{errorMessage}}
</div>
Channel Controller
[HttpPost("channels")]
public async System.Threading.Tasks.Task Create(Channel channel)
{
await _channelRepository.CreateChannel(channel);
}
Repository
public async System.Threading.Tasks.Task CreateChannel(Channel channel)
{
_context.Channel.Add(channel);
await _context.SaveChangesAsync();
}

Check if you name properties correctly in object that you send to server, property names are case sensitive. Looks like you have in js
var customer = {name: 'foo', lastName: 'bar'};
and on server you try to deserialize your JSON to this entity
class Customer {
public Name {get;set;} //note prop names are capitalized
public LastName {get;set;}
}

Related

Unable to redirect to homepage after posting a form - Express,EJS and JS

I have a view which contains a form and looks like this,
<form class="flex-form" id="form" method="">
<div class="form-component">
<label>Type</label>
<input type="text" id="type" name="type">
</div>
<div class="form-component">
<div class="form-component"><label><b>Contents</b></label></div>
<label>Savoury</label><input type="text" name="savoury" id="savoury">
<label>Fillings</label><input type="text" name="fillings" id="fillings">
<label>Amount</label><input type="text" name="amount" id="amount">
<div class="flex-component">
<button class="set-button" type="button" id="set">Set Item</button>
</div>
</div>
<div class="form-component">
<label class="description-label">Description</label>
<textarea class="fixed-textarea" id="description" name="description" cols="15" rows="10"></textarea>
</div>
<div class="form-component">
<label >Unit Price</label>
<input type="text" id="price" name="unit_price">
</div>
<div class="flex-component">
<button class="form-button" type="submit">Add</button>
</div>
</form>
I have a JavaScript that allows me to capture some intermediary information (via the Set Item button) from the form before the form gets submitted (via the Add Button). I want to handle the form's submission from the script since I need to capture the intermediary data.
let collectedItems = [];
let setter = document.getElementById('set');
let form = document.getElementById('form');
setter.addEventListener('click',getSetContent);
function getSetContent() {
let type = document.getElementById('savoury');
let fillings = document.getElementById('fillings');
let amount = document.getElementById('amount');
const content = {
type: type.value,
fillings: fillings.value.split(','),
amount: Number(amount.value)
};
collectedItems.push(content);
clearInputFields([type,fillings,amount]);
}
function clearInputFields(inputFields) {
inputFields.forEach(field => {
field.value = ''
});
console.log(collectedItems);
}
form.addEventListener('submit',submitForm);
function submitForm() {
const type = document.getElementById('type').value;
const desc = document.getElementById('description').value;
const price = Number(document.getElementById('price').value);
const content = collectedItems;
const data = {
type: type,
contents: content,
description: desc,
unit_price: price
};
post('http://localhost:8001/add/box',
{ 'Content-Type': 'application/json' },
JSON.stringify(data)
);
}
function post(endpoint,header,body) {
const response = fetch(endpoint,{ method: 'POST',headers: header,body: body });
response.then(
resp => {
if (resp.ok) {
console.log('form submitted');
} else {
console.log('form not submitted');
}
}
)
}
I then make a POST request using fetch() to an endpoint I have setup in Express which looks like this,
app.post('/add/box',(req,res) => {
const box: any = req.body;
console.log(box);
// DO SOME DB STUFF
res.redirect('/');
});
The form submission works as intended (logs to terminal using nodemon), however I am unable to redirect to the homepage. Instead I stay on the form page after the submission has occurred and I can't figure out why. Any help with this issue is much appreciated.

Search bar using Express and Node in MVC model

I have made a search bar on the customers page of my website and whatever string the admin enters in the search bar will be sent as a get request, and based on the input I am trying to find all the data in MySQL db which contains the input string inside of the fullname field.
My website build as MVC model, using Express to display data and Node.js
This is my form
<form class="d-flex" method="GET">
<input class="form-control me-2 py-1" type="text" id="search" name="search" placeholder="Search customer name" aria-label="Search" value="<%= %>" />
<button class="btn btn-sm btn-secondary" type="submit">Search</button>
</form>
This is route in web.js file
router.get('/customer?search',authentication.handleAuthentication, authadmin.authAdmin,adminController.searchCustomer);
getCustomerByName() inside adminServices.js
let getCustomerByName = (name) => {
return new Promise(async (resolve, reject) => {
try {
let user = await db.User.find({ fullname: name });
if (user) {
console.log(user);
resolve(user);
} else {
resolve(user);
}
} catch (e) {
reject(e);
}
});
};
searchCustomer() inside adminController.js
let searchCustomer = async (req,res,next) =>{
let name = req.params.search;
let customer = await adminServices.getCustomerByName(name);
return res.render('admin/customer.ejs', {
customer: customer,
});
}
I had tried req.body.search / req.params.search / req.query but seem like it can't get the input.
The URL like this: http://localhost:8080/customer?search=mai. I couldn't find where is the problem because there is nothing show in the console. Are there any method I could try?
You need to add action tag to form element. Change route name to just customer and use req.query.search in controller.
router.get('/customer', authentication.handleAuthentication, authadmin.authAdmin, adminController.searchCustomer);
let searchCustomer = async(req, res, next) => {
let name = req.query.search; // change params to query
let customer = await adminServices.getCustomerByName(name);
return res.render('admin/customer.ejs', {
customer: customer,
});
}
<form class="d-flex" action="/customer" method="GET">
<input class="form-control me-2 py-1" type="text" id="search" name="search" placeholder="Search customer name" aria-label="Search" value="<%= %>" />
<button class="btn btn-sm btn-secondary" type="submit">Search</button>
</form>

AngularJS how to put data and id when user send form

I would like to send my api date and newsId together with data from form.
This is my form:
<div class="well">
<h4>Leave a Comment:</h4>
<form role="form" ng-submit="createComm(newComment)" novalidate>
<div class="form-group">
<input type="text" class="form-control" placeholder="Autor" ng-model="newComment.author">
</div>
<div class="form-group">
<textarea class="form-control" ng-model="newComment.comment" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
Controller:
.controller('CommentController',
function($scope, $routeParams, NewsModel){
var newsId = $routeParams.id;
path = 'getCommetnsByNewsId/'+newsId;
var comm = this;
var data = new Date().toLocaleString();
//comm.newComm.data = data; //this way?
$scope.createComm = function(comment){
NewsModel.create(comment).then(function (result){
initCreateComm();
})
}
function initCreateComm(){
comm.newComm = { comment: '', author: '', data: '', id: ''};
}
})
and service
service.createComm = function(comm){
return $http.post(getUrl(),comm);
}
How can I add to this code to send data and newsId? I do not want to keep data and id as html input.
You could send it after form submitting on create comment request with angular.extend:
$scope.createComm = function(comment){
NewsModel.create(angular.extend({}, {data: data, newsId: newsId}, comment)).then(function (result){
initCreateComm();
})
}

Edit MEANJS list in the list page

I am using MEAN JS, i am trying to edit the list items on the list page, but it shows the error as below. i have initiated the data using ng-init="find()" for the list and ng-init="findOne()" for individual data.
Error: [$resource:badcfg] Error in resource configuration for action `get`. Expected response to contain an object but got an array
HTML
Below i the form inside the controller where it initiates the find() and findOne().
<div ng-controller="OrdersController" ng-init="find()">
<div>
<div class="order-filter">
<div ng-repeat="order in orders">
<form ng-init="findOne()" name="orderForm" class="form-horizontal" ng-submit="update(orderForm.$valid)" novalidate>
<input type="text" class="" ng-model="order.title">
<input type="text" class="" ng-model="order.content">
<div class="form-group">
<input type="submit" value="Update" class="btn btn-default">
</div>
</form>
</div>
</div>
</div>
</div>
Controller
$scope.update = function (isValid) {
$scope.error = null;
if (!isValid) {
$scope.$broadcast('show-errors-check-validity', 'orderForm');
return false;
}
var order = $scope.order;
order.$update(function () {
$location.path('orders/' + order._id);
}, function (errorResponse) {
$scope.error = errorResponse.data.message;
});
};
$scope.find = function () {
Orders.query(function loadedOrders(orders) {
orders.forEach(appendFood);
$scope.orders = orders;
});
};
$scope.findOne = function () {
$scope.order = Orders.get({
orderId: $stateParams.orderId
});
};
You need to check your Orders Service which probably is using $resource to provide your API requests (Orders.query)
It should look something like this:
function OrdersService($resource) {
return $resource('api/orders/:orderId', {
orderId: '#_id'
}, {
update: {
method: 'PUT'
}
});
}
The style may be different depending on which version of mean you're using. By default, the $resource query will expect an array of results, but if for some reason you've set "isArray" to false then it will expect an object.
https://docs.angularjs.org/api/ngResource/service/$resource

Passing complex object from Angularjs controller to MVC controller is not working

On Ajax call from Angular controller, i am passing a complex object as data. On MVC controller object has all null values.
I have MVC view as given below, which will be the boiler plate for Register customer View.
<div data-ng-app="customer" id="customer" data-ng-controller="rootViewModel">
<h2>{{ pageHeading }}</h2>
<hr />
<form id="formElement">
<div ng-view></div>
</form>
Using AngularJS, I will be loading the register customer view, mark of register customer view given below. I have register customer function tied to button using ng-click directive.
<fieldset class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-3">Company Name</label>
<div class="col-sm-4">
<input class="form-control inputfieldValidation" ng-model="customer.Name" type="text" placeholder="Full company name" required autofocus />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">PAN</label>
<div class="col-sm-4">
<input class="form-control" ng-model="customer.Pan" type="text">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">TIN</label>
<div class="col-sm-4">
<input class="form-control inputfieldValidation" ng-model="customer.Tin" type="text" required />
</div>
</div>
<button class="btn btn-primary proceedNext" id="registerCompany" ng-click="registerCompany(customer)">Register Customer</button>
</fieldset>
I have angular controller, which has function called registerCustomer() that will be called on click of register customer. I have an ajax call inside that function as given below.
customerModule.controller("CustomerRegistration", function ($scope) {
var initialize = function () {
}
$scope.registerCompany = function (customer) {
$.ajax({
url: 'Home/RegisterCompany',//make sure url exist
data: JSON.stringify({company: customer}),//pass data to action
type:'POST',
success: function (data) {
alert(JSON.stringify(data));
//window.location.href = '#Url.Action("Order")'; //redirect
}
});
}
initialize();
});
On MVC, i have a model called Company as given below.
public class Company
{
public string Name;
public string Pan;
public string Tin;
}
and my MVC controller look as
[HttpPost]
public JsonResult RegisterCompany(Company company)
{
//Do something
return null;
}
Always I have null object on MVC controller, please help me if am missing anything. Thanks in advance
EDIT: It looks like you need a view model in mvc or a modification to your post:
public class CompanyViewModel {
public Company company { get; set; }
}
Or use data: JSON.stringify(customer) instead of data: JSON.stringify({ company: customer })
Here is a working example from a website we are developing. It uses Riot.js instead of angular, but the concepts will be similar.
See also http://www.abeautifulsite.net/postjson-for-jquery/
$.getJSON(self.baseUrl + "/SaveApplicant", $('form.#applicant').serialize(), function (response) {
if (response.errorMessage) {
RiotControl.trigger('error_message', response.errorMessage);
return;
} else {
self.packageQuote.applicant = response;
}
RiotControl.trigger("continue","applicant");
});
Or using post, per the link above
$.post(self.baseUrl + "/SaveApplicant", $('form.#applicant').serialize(), function (response) {
if (response.errorMessage) {
RiotControl.trigger('error_message', response.errorMessage);
return;
} else {
self.packageQuote.census = response;
}
RiotControl.trigger("continue","applicant");
},'json');
There is a bit more involved on the MVC side of things, to send back a json response with lower case property name prefixes:
public ActionResult SaveApplicant(Applicant model)
{
if (ModelState.IsValid)
{
var applicant = DbContext.Applicants.FirstOrDefault(row => row.Id == model.Id);
if (applicant == null) {
DbContext.Applicants.Add(model);
} else {
applicant.Clone(model); // implement as needed or use entity state modified.
}
DbContext.SaveChanges();
return FormattedJsonResult(applicant);
}
return ModelErrors();
}
public ActionResult FormattedJsonResult(object model)
{
var camelCaseFormatter = new JsonSerializerSettings();
camelCaseFormatter.ContractResolver = new CamelCasePropertyNamesContractResolver();
var result = JsonConvert.SerializeObject(model, camelCaseFormatter);
return Content(result, "application/json");
}
public ActionResult ModelErrors()
{
return FormattedJsonResult(
new
{
errorMessage =
String.Join("\n",
ModelState.Values.SelectMany(value => value.Errors).Select(error => error.ErrorMessage))
});
return View();
}

Categories

Resources