When a button is clicked, I want to create a new User, and redirect the person to http://www.myapp.com/#/user/134.
The below code works, but am I using AngularJS factories correctly? It feels strange to have to define a 'createUser' function in my controller.
myApp.factory('User', ['$resource', function($resource) {
return $resource("/users/:id", { id: "#id" },
{
'create': { method: 'POST' },
'index': { method: 'GET', isArray: true },
'show': { method: 'GET', isArray: false },
'update': { method: 'PUT' },
'destroy': { method: 'DELETE' }
}
);
}]);
myApp.controller('splash', ['$scope', '$http', '$location', 'User', function($scope, $http, $location, User){
$scope.createUser = function(){
User.create(
{},
function(response){
$scope.user = response;
$location.path('/users/' + $scope.user.id);
},
function(){
console.log('error creating user');
});
}
}]);
Here is a view with a button for creating a new user:
<button ng-click="createUser()">Create User</button>
Related
What is the best way to send a request to the Amadeus API with a form field that uses autocomplete in a Rails app?
I am adding autocomplete to a search form to query the Amadeus "Airport and City Search".
I am using Rails 6 and gem 'amadeus'.
I get a 401 Unauthorized error when I type 3 letters into the search form. How can I authorize my request and make this autocomplete work?
Here is my javascript:
$(function() {
function log(message) {
$("<div>").text(message).prependTo("#log");
$("#log").scrollTop(0);
}
$("#city").autocomplete({
source: function(request, response) {
$.ajax({
url: "https://test.api.amadeus.com/v1/reference-data/locations",
dataType: "json",
data: {
apikey: "my_api_key_here",
keyword: request.term
},
success: function(data) {
response(data);
}
});
},
minLength: 3,
select: function(event, ui) {
log(ui.item ?
"Selected: " + ui.item.label :
"Nothing selected, input was " + this.value);
},
open: function() {
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function() {
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
});
Here is an authorized request with javascript using the gon gem to get the access token in javascript.
$(function() {
amadeus_client = gon.amadeus
function log(message) {
$("<div>").text(message).prependTo("#log");
$("#log").scrollTop(0);
}
console.log("Requesting Token...");
var settings = {
"url": "https://test.api.amadeus.com/v1/security/oauth2/token",
"method": "POST",
"timeout": 0,
"data": {
"client_id": amadeus_client.client_id,
"client_secret": amadeus_client.client_secret,
"grant_type": "client_credentials"
}
};
$.ajax(settings).done(function (response) {
console.log("Assigning Token variables...");
ACCESS_TOKEN = response.access_token;
console.log("Access Token : " + ACCESS_TOKEN);
});
$("#city").autocomplete({
source: function(request, response) {
$.ajax({
type: "get",
url: "https://test.api.amadeus.com/v1/reference-data/locations",
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization',
'Bearer ' + ACCESS_TOKEN);
},
data: {
keyword: request.term,
subType: "CITY"
},
success: function(data){
// console.log(data);
response($.map(data.data, function(el){
return {
label: el.detailedName,
value: el.iataCode
}
}));
}
});
},
minLength: 3,
select: function(event, ui) {
log(ui.item ?
"Selected: " + ui.item.label :
"Nothing selected, input was " + this.value);
},
open: function() {
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function() {
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
});
I'm using jqgrid and when deleting a row in the grid i get the alert "Delete selected record?" and when i click ok i have written a code in onClickSubmit to make a ajax call to the controller which takes some parameters and delete the record. The functionality works fine.
But when i click "Delete" button in the alert i get an error "No url is set". Now, i have a url inside my ajax call which does the function. Why is the error thrown?
jqGrid:
var selectedRowId = "125";
$("#AttachmentsGrid").jqGrid({
url: '#Url.Action("LoadTransactionAttachments", "Home")',
postData: { 'transactionId': selectedRowId },
mtype: 'GET',
datatype: 'json',
jsonReader: {
id: 'AttachmentId',
repeatitems: false
},
height: 'auto',
hidegrid: false,
rownumbers: true,
autowidth: true,
shrinkToFit: false,
rowNum: 10,
pager: '#AttachmentsPager',
caption: "Attachments",
colNames: ['AttachmentName'],
colModel: [{ name: 'AttachmentName', index: 'AttachmentName', formatter: imageFormatter, unformat: imageUnFormatter }],
beforeRequest: function () {
responsive_jqgrid($(".jqGrid"));
},
onSelectRow: function (id) {
var statusId;
attachmentId = id;
var selectValues = jQuery('#AttachmentsGrid').jqGrid('getRowData', id);
attachmentName = selectValues.AttachmentName;
if (accessLevel.HasDeleteAttachmentAccess == true)
$("#del_AttachmentsGrid").show();
else
$("#del_AttachmentsGrid").hide();
},
loadComplete: function () {
UnBlockUI();
}
});
jQuery("#AttachmentsGrid").jqGrid('navGrid', '#AttachmentsPager', {
edit: false, add: false, del: true, search: false, refresh: true, refreshtext: ""
}, {}, {}, {
// url: '#Url.Action("UpdateDummyData", "Home")',
// Delete attachment event.
onclickSubmit: function (response, postData) {
$.ajax({
url: '#Url.Action("DeleteSelectedTransactionAttachment", "Home")',
datatype: 'json',
data: { 'attachmentId': JSON.stringify(postData), 'attachmentName': attachmentName, 'transactionId': selectedRowId },
type: 'POST',
success: OnCompleteDeleteAttachments,
error: function (xhr, status, error) {
if (xhr.statusText == "Session TimeOut/UnAuthorized") {
alert(xhr.statusText);
window.location.href = '#Url.Action("LogOut", "Account")';
}
else
alert(xhr.responseText);
}
});
It works when i give some Dummy url in delete method which i dont need. I need another way to solve this.?
FYI, This happens for me also during the edit of a row using form editing.
It seems to me that you try to use Delete in a wrong way. What you do is making Ajax request to '#Url.Action("DeleteSelectedTransactionAttachment", "Home")' with some additional data, do some unknown additional action inside of OnCompleteDeleteAttachments in case of successful deleting and do additional error handling in case of "Session TimeOut/UnAuthorized" error in statusText.
I think that correct implementation should looks more as the following
jQuery("#AttachmentsGrid").jqGrid('navGrid', '#AttachmentsPager', {
edit: false, add: false, search: false, refreshtext: ""
}, {}, {}, {
url: '#Url.Action("DeleteSelectedTransactionAttachment", "Home")',
serializeDelData: function (postData) {
return {
attachmentId: JSON.stringify(postData),
attachmentName: attachmentName,
transactionId: selectedRowId
}
},
errorTextFormat: function (xhr) {
if (xhr.statusText == "Session TimeOut/UnAuthorized") {
window.location.href = '#Url.Action("LogOut", "Account")';
} else {
return xhr.responseText;
}
},
afterSubmit: OnCompleteDeleteAttachments
});
I am trying to update a customers feedback post, the POST & DELETE work but I have been stuck on the PUT for a couple of days. any help will be great. thanks
Factory
app.factory('Post', function ($resource) {
return $resource('/api/apiPost/:id',
{ id: '#id' },
{ 'save': { method: 'POST' } },
{ 'update': { method: 'PUT' } },
{ 'query': { method: 'GET', isArray: false } });
});
CONTROLLER
$scope.updatePost = function (post) {
//alert("WORKS");
Post.update({ id: post.PostId }, $scope.post, function () {
$scope.postArray.push(post);
$scope.post = {
Title: '',
Body: ''
};
}, function () { });
}
ADAPTER
public Post PutNewPost(int id, Post newPost)
{
Post post = new Post();
post.PostId = newPost.PostId;
post.Title = newPost.Title;
post.Body = newPost.Body;
post.Hidden = newPost.Hidden;
db.Posts.Add(post);
db.SaveChanges();
return db.Posts.FirstOrDefault();
}
API CONTROLLER
// PUT api/<controller>/5
[Authorize(Roles = "Admin")]
public IHttpActionResult Put(int id, [FromBody]Post newPost)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok(_adapter.PutNewPost(id, newPost));
}
ERROR MESSAGE
TypeError: undefined is not a function
at h.$scope.updatePost (https://localhost:44301/MyScripts/AjaxPostController.js:40:14)
at https://localhost:44301/Scripts/angular.min.js:169:382
at https://localhost:44301/Scripts/angular.min.js:186:390
at h.$eval (https://localhost:44301/Scripts/angular.min.js:108:40)
at h.$apply (https://localhost:44301/Scripts/angular.min.js:108:318)
at HTMLInputElement.<anonymous> (https://localhost:44301/Scripts/angular.min.js:186:372)
at HTMLInputElement.o.event.dispatch (https://localhost:44301/Scripts/jquery-2.1.0.min.js:3:6055)
at HTMLInputElement.r.handle (https://localhost:44301/Scripts/jquery-2.1.0.min.js:3:2830)
I think your method arguments for $resource are mistaken. Return all your custom methods in 1 object like this:
app.factory('Post', function ($resource) {
return $resource('/api/apiPost/:id',
{ id: '#id' },
{
'save': { method: 'POST' },
'update': { method: 'PUT' },
'query': { method: 'GET', isArray: false }
}
);
I am starting with Angularjs + rails backend and trying to fetch users data from the server - equivalent to to controller/index action in rails.
I have followed several tutorials and found this code as the most clear one....
questions
1. How to properly link angular module into views ?
2. How to fetch data using typeahead and sample data in this post.
here is plunker version of the code
Code is as follows:
views
<div ng-app='users'>
<div class='container-fluid' ng-controller="UsersIndexCtrl">
<pre>Model: {{result | json}}</pre>
<input type="text" ng-model="result" typeahead="suggestion for suggestion in users($viewValue)">
</div>
</div>
controller
<script>
// ['ui.bootstrap', 'ngResource'])
var app = angular.module('users', ['ui.bootstrap', 'ngResource']);
// factory - resources users
// equivalent to rails users/index
app.factory('Users', function($resource) {
return $resource('/users.json', {}, {
index: { method: 'GET', isArray: true}
});
});
// factory - user resource
// equivalent to users show, update
app.factory('User', function($resource) {
return $resource('/users/:user_id.json', {}, {
show: { method: 'GET' },
update: { method: 'PUT' }
});
});
// controller - users/ index
// equivalent to rails controller rails/index
var UsersIndexCtrl = function($scope, users) {
$scope.users = users;
};
</script>
and I am stack here, as I am getting this error:
Error: Unknown provider: usersProvider <- users
The goal of this code is to use typehead and provide data to the user.
My '/users.json' url is as follows:
[{"full_name":"Lia Cartwright","id":1,"image_url":"no-icon.jpg"},{"full_name":"Hilton Turner","id":2,"image_url":"no-icon.jpg"},{"full_name":"Aubrey Barrows","id":3,"image_url":"no-icon.jpg"},{"full_name":"Donnie Kris","id":4,"image_url":"no-icon.jpg"},{"full_name":"Eryn Rath","id":5,"image_url":"no-icon.jpg"},{"full_name":"Caden Fay","id":6,"image_url":"no-icon.jpg"},{"full_name":"Arlie Tromp","id":7,"image_url":"no-icon.jpg"},{"full_name":"Rico Klein","id":8,"image_url":"no-icon.jpg"},{"full_name":"Gudrun Dare","id":9,"image_url":"no-icon.jpg"},{"full_name":"Nathan Langworth","id":10,"image_url":"no-icon.jpg"},{"full_name":"Deanna Stroman","id":11,"image_url":"no-icon.jpg"},{"full_name":"Shania Stroman","id":12,"image_url":"no-icon.jpg"},{"full_name":"Lupe Harvey","id":13,"image_url":"no-icon.jpg"},{"full_name":"Constance Armstrong","id":14,"image_url":"no-icon.jpg"},{"full_name":"Reagan Tremblay","id":15,"image_url":"no-icon.jpg"},{"full_name":"Murray Sipes","id":16,"image_url":"no-icon.jpg"},{"full_name":"Dandre Klocko","id":17,"image_url":"no-icon.jpg"},{"full_name":"Haylee Monahan","id":18,"image_url":"no-icon.jpg"},{"full_name":"Florence Harber","id":19,"image_url":"no-icon.jpg"},{"full_name":"Norberto Hoppe","id":20,"image_url":"no-icon.jpg"}]
You must inject Users not users, it's case sensitive.
Side notes:
No need to create two models, replace:
app.factory('Users', function($resource) {
return $resource('/users.json', {}, {
index: { method: 'GET', isArray: true}
});
});
app.factory('User', function($resource) {
return $resource('/users/:user_id.json', {}, {
show: { method: 'GET' },
update: { method: 'PUT' }
});
});
with:
app.factory('User', function($resource) {
return $resource("users/:id", { id: '#id' }, {
index: { method: 'GET', isArray: true, responseType: 'json' },
show: { method: 'GET', responseType: 'json' },
update: { method: 'PUT', responseType: 'json' }
});
})
Other thing, in your controller, do:
var UsersIndexCtrl = function($scope, User) {
$scope.users = User.index();
};
Last thing, consider using: Angular Rails resource
I've got a problem using ASP.NET MVC3, AJAX and JQUERY. I've got the following function
[HttpPost]
public bool Update(int id, FormCollection collection)
This is my jQuery Source:
$(document).ready(function () {
$('#btnUpdate').click(function (e) {
// Cancel default action
e.preventDefault();
var formCollection = $('#formId').serialize();
$.ajax({
cache: false,
type: 'POST',
url: '#Url.Action("Action","Controller")',
data: { id: $('#id').val(), collection: formCollection },
success: function (data) {
alert(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error during process: \n' + xhr.responseText);
}
});
});
});
The id parameter submitted successfully, but the collection (FormCollection) includes an array with {[0]: 10000, [1]: collection}. I can't fix the problem. When I redesign the solution like this:
[HttpPost]
public bool Update(FormCollection collection)
$(document).ready(function () {
$('#btnUpdate').click(function (e) {
// Cancel default action
e.preventDefault();
$.ajax({
cache: false,
type: 'POST',
url: '#Url.Action("Action", "Controller")',
data: $('#formId').serialize(),
success: function (data) {
alert(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error during process: \n' + xhr.responseText);
}
});
});
});
everything works fine. What I'm doing wrong in passing 2 parameter?
THX!!!
Try calling JSON.stringify() on your JSON:
data: JSON.stringify({ id: $('#id').val(), collection: formCollection })
$(document).ready(function () {
$('#btnUpdate').click(function (e) {
// Cancel default action
e.preventDefault();
var formCollection = $('#formId').serialize();
$.ajax({
cache: false,
type: 'POST',
url: '#Url.Action("Action","Controller")',
data: JSON.stringify({ id: $('#id').val(), collection: formCollection }),
success: function (data) {
alert(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error during process: \n' + xhr.responseText);
}
});
});
});
you should have to pass the data with jsonstringify
This is the actual watch:
Parameter ID submitted successfully (Name=id, Wert=10000). Above id you can see formCollection including FORM.serialize() values of the ajax call. But the System.Web.Mvc.FormCollection including two keys only: id and collection! I expected
"Name"
"Address"
"Address_2"
...
I think if got a mistake in creating my ajax request, but I don't know why...
var customerNo = $('#fieldID').val();
var formCollection = $('#formID').serialize();
$.ajax({
cache: false,
type: 'POST',
url: '#Url.Action("Action", "Controller")',
data: { id: customerNo, collection: formCollection },
dataType: 'json',
success: function (data) {
if (data) {
alert(data);
};
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error during process: \n' + xhr.responseText);
}
});
The following line generates an error:
data: JSON.stringify({ id: customerNo, collection: formCollection })
The parameters dictionary contains a null entry 'id' of non-nullable type 'System.Int32'...
Changed without effect:
data: { id: customerNo, collection: JSON.stringify(formCollection) },
Any ideas?
This is my idea (works!)
Add in a partial class from a model an string attribute, add this attribute manually in "data".
JS:
$.ajax({
cache: false,
type: 'POST',
url: '#Url.Action("Action", "Controller")',
data: $("form").serialize() + "&id=whatever",
dataType: 'json',
success: function (data) {
if (data) {
alert(data);
};
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error during process: \n' + xhr.responseText);
}
});
partialClass.cs Model:
public partial class TableName
{
public string id { get; set; }
}
Controller:
[HttpPost]
public bool Update(FormCollection collection){
var ID = collection.id;
}
Regards!