How to update a resource using AngulaJS Rails Resource - ruby-on-rails

I'm using AngularJS Rails Resource and have it configured like so:
angular.module('admin')
.factory('Page', ['railsResourceFactory', 'API_PROVIDER', function(railsResourceFactory, API_PROVIDER) {
return railsResourceFactory({
url: API_PROVIDER.full_path + 'pages', //which resolves to https://example/api/pages
name: 'page'
});
}]);
And in my controller:
(function() {
'use strict';
angular
.module('admin')
.controller('PagesEditController', PagesEditController);
/** #ngInject */
function PagesEditController($timeout, webDevTec, toastr, $scope, $moment, Page, Session, $http, $location, $anchorScroll, $stateParams) {
$http.defaults.headers.common.Authorization = 'Token token='+ Session.token;
var page = Page.get($stateParams.pageId).then(function (result) {
$scope.editPage = result;
});
$scope.savePage = function (page) {
page.update();
}
}
})();
In my view I have:
...
<input type="text" ng-model='editPage.title' class="form-control underline-input">
<button ng-click='savePage(editPage)' class="btn btn-green btn-ef btn-ef-7 btn-ef-7h" activate-button="success"><i class="fa fa-envelope"></i> Save page</button>
...
EDIT: My save function:
$scope.savePage = function (page) {
Page.get($stateParams.pageId).then(function (result) {
result.title = $scope.editPage.title;
result.content = $scope.editPage.content;
result.update();
})
}
But its not working. I get an error like so: No route matches [PUT] "/api/pages" which means the PUT request is not passing the object id when submitting the request.
I'm using Mongoid btw.
What am I missing here?

Related

MVC partial in modal posting wrong model

My partial view which is loaded into a bootstrap partial on my Index page, should be posting type Announcement but is posting type AnnouncementViewModel of the Index page model to the Create controller.
The #modal-container is specified in my _Layout, which is working as expected.
Unsure about the controllers - they appear correct, the problem is stemming from my ajax post I believe but I don't know what's the issue. I get the error after POST, however the database does update with the model correctly, but afterwards I get the below error.
I have specified $('#create-container')/$('form') as the form in which to serialize and send back to the controller.
Why is it doing this?
Error:
The model item passed into the dictionary is of type 'AnnouncementsViewModel', but this dictionary requires a model item of type 'Announcement'.
Index:
#model AnnouncementsViewModel
<h2>Announcements</h2>
<div>
#Html.ActionLink("Create", "Create", "Announcements", null, new { #class = "modal-link btn btn-sm" })
<div class="announcementTable">
<div id="announcementList">
#{Html.RenderPartial("List", Model.AnnouncementList);}
</div>
</div>
</div>
Partial:
#model Announcement
#section Scripts {
<script type="text/javascript">
$(function () {
$('#btn-create').click(function () {
$.ajax({
url: '#Url.Action("Create","Announcements")',
type: 'POST',
contentType: 'application/json',
data: $('#create-container').serialize(),
success: function (data) {
if (data.success == true) {
$('#modal-container').modal('hide');
location.reload(false)
} else {
$('#modal-container').html(data);
}
}
})
});
$('#btn-close').click(function () {
$('#modal-container').modal('hide');
});
});
</script>
}
<div class="create-container">
#using (Html.BeginForm())
{
<div class="newAnnouncementTableRow1">
<div>#Html.LabelFor(m => m.Title)</div>
<div>#Html.EditorFor(m => m.Title)</div>
<div>#Html.LabelFor(m => m.Details)</div>
<div>#Html.EditorFor(m => m.Details)</div>
</div>
<div class="newAnnouncementTableRow2">
<div>#Html.LabelFor(m => m.StartDT)</div>
<div>#Html.EditorFor(m => m.StartDT)</div>
<div>#Html.LabelFor(m => m.ExpiryDT)</div>
<div>#Html.EditorFor(m => m.ExpiryDT)</div>
<div>#Html.LabelFor(m => m.Enabled)</div>
<div>
#Html.RadioButtonFor(m => m.Enabled, 1)Yes
#Html.RadioButtonFor(m => m.Enabled, 0, new { #checked = "checked" })No
</div>
</div>
<div>
<button type="submit" id="btn-create" class="btn btn-sm">Save</button>
<button type="button" class="btn btn-default modal-close-btn" data-dissmiss="modal">Cancel</button>
</div>
}
</div>
Controller:
[HttpGet]
public ActionResult Index()
{
var avm = new AnnouncementsViewModel
{
AnnouncementList = new List<Announcement>()
};
avm.AnnouncementList = GetAnnouncementList();
return View(avm);
}
[HttpGet]
public ActionResult Create()
{
return PartialView("Create");
}
[HttpPost]
public ActionResult Create(Announcement a)
{
db.DbAnnouncement.Add(a);
db.SaveChanges();
return Index();
}
You set contentType: 'application/json' it your .ajax() call but returning View from Controller. Either change contentType to html or change controller to return JsonResult and return Json("yourData");
I recommend you to change your ajax call:
$.ajax({
/* other data */
dataType : "html",
contentType: "application/json; charset=utf-8",
/* other data */
success: function (data) {
$('#modal-container').modal('hide');
location.reload(false)
},
error: function (jqXHR, textStatus, errorThrown )
{
$('#modal-container').html(data);
}
/* other data */
});
Thing is response from server in your case always success but it returns html rather than json so you just don't have data.success at all.
The other issue as mentioned in the comments was that the controller was redirecting to an action method that it could not.
Changing return Index(); to return RedirectToAction("Index", "Announcements"); solved the error and the redirecting to the Create partial page caused by using return View();.

AngularJS form data to Ruby on Rails API

I created a simple API with Ruby on Rails,and I'm trying to send data from a form with AngularJS. The thing is that the App is sending the post method and the backend is creating the new records, so far it's working, but it creates it with Null values.
This is the form:
<div ng-controller="postController">
<form name="messageForm" ng-submit="submitForm()">
<div class="form-group">
<label>Name</label>
<input type="text" name="content" class="form-control" ng-model="message.content">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
This is the Angular Controller:
app.controller('postController', function($scope, $http) {
// create a blank object to handle form data.
$scope.message = {};
// calling our submit function.
$scope.submitForm = function() {
$http({
method : 'POST',
url : 'http://localhost:3000/api/v1/messages',
data : $scope.message, //forms user object
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function(data) {
if (data.errors) {
// Showing errors.
$scope.errorContent = data.errors.errorContent;
} else {
$scope.message = data.message;
}
});
};
});
And in the RoR's API Controller, this is the Create method:
def create
respond_with Message.create(params[:message])
end
The only rows are:
ID which is generated automatically.
And 'content'
You must assign a key to your message object in data parameter, like this:
$http({
method : 'POST',
url : 'http://localhost:3000/api/v1/messages',
data : { data: $scope.message },
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
})
.sucess(function(data){ ... });
And then, in your controller:
def create
respond_with Message.create(params[:data])
end
Hope this help :)

Quick Search Form Not Submitting MVC

I currently have a partial view that renders at the top of every page on the site. The point of this partial view is to provide a form that lets the user do a quick search. I have set the partial view form up as follows:
#using (Html.BeginForm())
{
<div class="col-md-7" style="text-align: right">
<div class="input-group input-group-sm col-sm-6 pull-right">
#Html.TextBox("caseReference")
<button type="submit">
<i class="fa fa-search"></i>
</button>
</div>
</div>
}
#Html.Partial("_MainNavigation")
</div>
</div>
</nav>
<script type="text/javascript">
$(function () {
$("form").on("submit", function (event) {
event.preventDefault();
var request = { caseReference: $('#caseReference').val() };
submitForm(request, '#Url.Action("CaseSearch", "QuickSearch", new { area = "Search" })');
});
});
</script>
However under the page source the form action renders as a request to the home page with a post action. I have read numerous examples and this task seems very straight forward. Would it be a better idea to use the parameters on the #html.BeginForm() method?
So after spending a few hours researching, I have finally got the quick search functionality to work on the home page of my site. In the razorview I have the following code:
<div class="input-group input-group-sm col-sm-6 pull-right">
#Html.Kendo().MaskedTextBox().Name("name").Mask("000000/0000").Deferred()
<button id="search" type="submit">
<i class="fa fa-search"></i>
</button>
<script type="text/javascript">
$(function () {
$("#search").on("click", function (event) {
event.preventDefault();
var value = $('#name').val();
value = value.replace(/[/]/g, "_");
var refVal = value;
var url = '#Url.Action("Action", "Contoller", new { area = "Area" })' + '//' + refVal;
$.ajax({
type: 'GET',
url: url,
cache: false,
dataType: 'json',
contentType: "application/json;",
success: function (result) {
if (result.success) {
window.location.href = result.url;
}
else {
bootbox.alert(result.message);
}
}
});
});
});
However in regards to the following line:
var url = '#Url.Action("Action", "Contoller", new { area = "Area" })' + '//' + refVal;
If I hard code the url and append the search term it works on the Home page because we are at the root directory but from other pages it fails, To get around this I tried to use #Url.Action. However this is producing the following result in the html soure code:
var url = '' + '//' + refVal;
Is there a certain way to use the URL.Action method from withing JS?

Parameter passed from view to controller not working

I have a very simple view and can't figure out why my textbox value is not passing to my controller. Will the actionlink work for providing the controller the parameter?
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm("LookupEmployee", "Home")) {
<div class="jumbotron">
<h2>Personnel System</h2><br />
<p>ID: <input type="text" id=employeeID name="employeeID" /></p>
#Html.ActionLink("Your Leave Balance", "LeaveBalance", "Home", null, new { #class = "btn btn-primary btn-large" })
</div>
}
<div class="row">
</div>
My HomeController takes the parameter and fills the dataset. I have hard coded a value and verified that this code works:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult LeaveBalance(string employeeID)
{
//ViewBag.Message = "Your application description page.";
if (!String.IsNullOrEmpty(employeeID))
{
DataSet gotData;
LeaveRequestWCF myDataModel = new LeaveRequestWCF();
gotData = myDataModel.GetTheData(Convert.ToInt32(employeeID));
myDataModel.theModelSet = gotData;
return View(myDataModel);
}
return View();
}
}
Any advice? As you can tell, I'm new with MVC and trying to drift away from web forms.
OPTION 1:
You are using Html.ActionLink to post a form, which cannot be done because Html.ActionLinks are rendered as Anchor tags. Anchor tags make GET Requests unless we explicitly handle their JQuery click event. Use a Submit button to post a form for an appropriate controller action. So instead of -
#Html.ActionLink("Your Leave Balance", "LeaveBalance", "Home", null,
new { #class = "btn btn-primary btn-large" })
go for -
<input type="submit" class="SomeClass" value="Submit" />
OPTION 2:
You can also use AJAX POST using JQuery click event for anchor tag to post the form and once you get the result, you can make a client side redirection.
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
$(document).ready(function() {
$("#solTitle a").click(function() {
var data = {
"Id": $("#TextId").val()
};
$.ajax({
type: "POST",
url: "http://localhost:23133/api/values",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
dataType: "json",
processData: true,
success: function (data, status, jqXHR) {
console.log(data);
console.log(status);
console.log(jqXHR);
alert("success..." + data);
// handle redirection here
},
error: function (xhr) {
alert(xhr.responseText);
}
});
});
});
</script>
ActionLink creates a simple <a href /> on the page, that will send a get request to the server.
You need a submit button instead, so your form gets posted with its form inputs. Use:
<button type="submit">Your Leave Balance</button>

Ajax.BeginForm - Get element which makes request

I have some ajax forms in my page and I need to get the form Id or some element inside the form when the OnSuccess function is called, example:
<li>
#using (Ajax.BeginForm(new AjaxOptions
{
OnSuccess = "form.onSuccess"
}))
{
#Html.TextBoxFor(m => m.TaskId)
<button type="submit">Save</button>
}
</li>
how can I get?
Option 1:
#using (Ajax.BeginForm(new AjaxOptions{OnComplete = "DefaultEditOnComplete(xhr, status, 'Person')"}))
{
//Person data and submit button
}
function DefaultEditOnComplete(xhr, status, entityName) {
//xhr - the ajax response
//status - the response text, ex. "success"
//entityName - your custom argument, in this example 'Person'
alert('DefaultEditOnComplete fired for ' + entityName);
}
Option 2:
$('form').submit(function () {
$(this).addClass('activeForm');
});
#using (Ajax.BeginForm(new AjaxOptions{OnSuccess= "JaxSuccess(xhr, status)"}))
{
....
}
function JaxSuccess(xhr, status) {
var active = $(".activeForm");
//Do some stuff here
.....
//When Done, remove the activeForm class, making everything clean
$(".activeForm").removeClass('activeForm');
}
Option 3:
Abandon Ajax.BeginForm, and substitute for regular form and jquery pairing:
#using (Html.BeginForm("SomethingNice", "Home", FormMethod.Post, new { #id = "CoolForm", #class = "ajaxForm" }))
{
#Html.LabelFor(m => m.Rating)
#Html.TextBoxFor(m => m.Rating)
#Html.LabelFor(m => m.Comment)
#Html.TextBoxFor(m => m.Comment)
<input type="submit" value="Submit"/>
}
<script type="text/javascript">
$(function() {
$(".ajaxForm").submit(function(e) {
e.preventDefault();
var form = $(this);
var jaxUrl = form.attr('action');
var dat = form.serialize();
alert(form.attr('id'));
$.ajax({
url: jaxUrl,
data: dat,
success: function(data) {
form.parent().append(data);
},
error: function(xhr, status) {
}
});
});
});
</script>

Resources