Backbone routing loading data-role=page - jquery-mobile

I have a mobile app built using jquery mobile and backbone. I'm trying to work through the routing logic to render my views accordingly and am thus starting simple and adding complexity as I go along.
The html is as follows
<div id="main">
<li>Click Here to Test Me</li>
</div>
<div id="view-goes-here"></div>
<script type="text/template" id="actions-template">
<table cellspacing='0' cellpadding='0' border='1' >
<thead>
<tr>
<th>Id</th>
<th>Str</th>
</tr>
</thead>
<tbody>
<% _.each(action, function(c) { %>
<% var f = c.id, g = c.str; %>
<tr>
<td class="<%= f %>"><%= c.id %></td>
<td class="<%= g %>"><%= c.str %></td>
</tr>
<% }); %>
</tbody>
</table>
</script>
Here is a jsfiddle with functional code: http://jsfiddle.net/horcle_buzz/4JGhZ/
I would like it so that when I do a hashchange to "test_me" then the contents of the "main" div (specifically, the url with text "Click Here to Test Me") would disappear with only the output from my view being rendered in the output, specifically the table contents from my variable c in the function test:
var c = [
{ id: 1, str: 'This'},
{ id: 2, str: 'is'},
{ id: 3, str: 'a'},
{ id: 4, str: 'test!'}
];
My view is as follows:
var ActionView = Backbone.View.extend({
template: ActionTemplate,
events:{
"click":"makeInput"
},
render:function(){
alert("a" + JSON.stringify(this.collection));
alert("b" + this.collection.toJSON());
$(this.el).html(this.template({
action: this.collection.toJSON()
}));
$('#view-goes-here').append(this.el);
return this;
},
makeInput:function(){
alert("im in");
}
});
My guess is that I would have to use the data-role=page tag for my divs, but when I do this, the view does not render as expected. I am slightly confused about how to get the desired output, especially since most examples out there are rather basic.
I disable jQuery Mobile routing as follows and then start Backbone history:
$(document).ready(function(){
$.mobile.linkBindingEnabled = false;
$.mobile.hashListeningEnabled = false;
var router = new ActionsRoute();
Backbone.history.start();
});
Routing is done as follows:
var ActionsRoute = Backbone.Router.extend({
routes: {
'': 'main',
'test_me': 'loader'
},
main: function() {
$.mobile.changePage( "#main" , { reverse: false, changeHash: false } );
},
loader: function() {
test(function(c, Actions, ActionView){
alert("Data:" + JSON.stringify(c));
var actions = new Actions(c);
var actionView = new ActionView({collection:actions});
actionView.render();
});
}
});
Thanks in advance!

Doh! I did not have jquery.mobile-1.2.0.min.css defined as a resource. Added it, and all is behaving as desired.

Related

Pass Object Parameter from javascript\ajax to function in Controller

I have a table that i want to be able to update the status of each line that checkbox is on
(see attached screenshot)
The checkbox propery in the Model is Not Mapped to the database ([NotMapped])
Html:
<div class="row">
<div class="col-12 text-right">
<button class="btn btn-primary" onclick="ApproveStatus()">Approve Checked Lines</button>
</div>
</div>
javaScript:
#section Scripts{
<script type="text/javascript">
function ApproveStatus() {
var pdata = new FormData();
swal({
title: "Are you sure?",
text: "Once Updated, you will not be able to Undo this",
icon: "warning",
buttons: true,
dangerMode: true,
})
.then((willDelete) => {
if (willDelete) {
$.ajax({
url: "PaymentHistory/ApproveStatus",
type: "POST",
data: pdata,
processData: false,
contentType: false,
success: function (data) {
swal("Success!", {
icon: "success",
});
}
});
setTimeout(function () {
location.reload()
}, 100);
} else {
swal("Nothing Changed!");
}
});
}
</script>
}
And in the Controller i have the function (haven't written the logic yet)
[HttpPost]
public IActionResult ApproveStatus()
{
}
table in html:
<table id="tblData" class="table table-striped table-bordered" style="width:100%">
<thead class="thead-dark">
<tr class="table-info">
<th>Address</th>
<th>Payment Type</th>
<th>Amount</th>
<th>Payment Date</th>
<th>Status</th>
<th></th>
</thead>
#foreach (PaymentHistory paymentHistory in Model)
{
<tr>
<td>#ViewBag.getPaymentAddress(paymentHistory.SentFromAddressId).ToString()</td> <td>#ViewBag.getPaymentType(paymentHistory.SentFromAddressId).ToString()</td>
<td>#paymentHistory.Amount$</td>
<td>#paymentHistory.PayDate</td>
<td>#paymentHistory.Status</td>
#if (paymentHistory.Status != "Approved")
{
<td>
<div class="text-center">
<input type="checkbox" asp-for="#paymentHistory.isChecked"/>
</div>
</td>
}
else
{
<td></td>
}
</tr>
}
</table>
My only issue is that i want to pass the Object from the View (that contains the lines and status of the checkbox) to the function in the controller as a parameter,
Any ideas how can i do this?
Thank you
i want to pass the Object from the View (that contains the lines and status of the checkbox) to the function in the controller as a parameter, Any ideas how can i do this?
To achieve your requirement, you can try to add a hidden field for SentFromAddressId field, like below.
<td>
<div class="text-center">
<input type="hidden" asp-for="#paymentHistory.SentFromAddressId" />
<input type="checkbox" asp-for="#paymentHistory.isChecked" />
</div>
</td>
then you can get the sentFromAddressId of each checked row and populate it in form data object.
var pdata = new FormData();
$("input[name='paymentHistory.isChecked']:checked").each(function (index, el) {
var sentFromAddressId = $(this).siblings("input[type='hidden']").val();
pdata.append("Ids", sentFromAddressId);
})
and post the data to action method with following code snippet.
$.ajax({
type: 'POST',
url: '/PaymentHistory/ApproveStatus',
data: pdata,
processData: false,
contentType: false,
datatype: 'json',
success: function (res) {
//...
}
});
ApproveStatus action method
public IActionResult ApproveStatus(int[] Ids)
{
//code logic here
//update corresponding record based on id within Ids
Get all checked checkboxes id in an array, use that array to update table

MVC WebGrid paging action changing upon navigation

I'm working in an MVC app that is using a webgrid with paging. The grid itself is rendered in a partial view called _Results.cshtml and is rendered in a div on the index.cshtml page using
Html.RenderPartial("_Results", Model.Results);
The partial grid as well as a few other form controls on index.cshtml are wrapped in a form called ResultsAction using:
#using (Ajax.BeginForm("ResultsAction", "Results", new AjaxOptions.....
When intially navigating to the index.cshtml, the grid populates as expected and hovering over any of the paging links correctly display:
http://localhost/ResultsAction?page=<page#>
Each row in the grid has a link to a detail page. This works as expected and the detail page has a link to return to the result grid using:
#Html.ActionLink("Return To Results", "Index", "Results")
Now the problem. This redirects me back to the Index.cshtml just fine but now when I hover over any of the paging links in the grid, they incorrectly are using:
http://localhost/Index?page=<page#>
Which is the wrong controller action so paging no longer functions. My understanding was the paging links should issue a Get using the form name as the action, yet it's being overridden somehow when I navigate to detail then back again. Does anyone know what's causing this behavior or how I can specify the paging links to always use the same controller action?
EDIT: Posting code of partial view as requested:
#model IEnumerable<ispPR_GetInquiryRecords_Result>
#{
Layout = null;
}
<input id="searchListCnt" type="hidden" value="#Model.Count()" />
<div id="gridSearch">
#{
var grid = new WebGrid(selectionFieldName: "SelectedRow", canSort: false, canPage: true, rowsPerPage: 10, ajaxUpdateContainerId: "gridSearch");
var virtualCount = Model != null && Model.Count() > 0 ? Model.First().VirtualCount : 0;
grid.Bind(Model, rowCount: (int)virtualCount, autoSortAndPage: false);
}
<div id="gridContent">
#grid.GetHtml(
htmlAttributes: new { id = "inqgrid" },
tableStyle: "webGrid",
fillEmptyRows: false,
footerStyle: "gridFooter",
displayHeader: true,
alternatingRowStyle: "alt",
selectedRowStyle: "select",
mode: WebGridPagerModes.All,
columns: grid.Columns(
grid.Column("PriceStatus",header:"Price Status"),
grid.Column("CustomerName","Customer Name"),
grid.Column("EndUserName", "End User"),
grid.Column("ContractNumber","Contract"),
grid.Column("PriceLevel", "Level"),
grid.Column("ProductDescription", "Product Code"),
grid.Column(
header: "Break Qty",
format: #<text>#item.QuantityBreak.ToString() / #item.QuantityBreakUOM </text>
),
grid.Column("BeginDate", "Begin Date", format: item =>string.Format("{0:d}", item.BeginDate)),
grid.Column("EndDate","End Date",format: item =>string.Format("{0:d}", item.EndDate)),
grid.Column(
header: "Price in PricingUOM",
format: item =>
{
var res = Html.FormatToDecimals((decimal)item.PriceInPricingUOM, (int)item.Numdecimals);
switch ((bool)#item.HasDetail)
{
case true:
return Html.ActionLink(res + " / " + (string)item.PricingUOM, "InquiryDetails", new { #id = #item.PriceMasterID }, new { #class = "item-link2", #id = "lnk_" + #item.PriceMasterID });
case false:
return Html.ActionLink(res+ " / " + (string)item.PricingUOM, null, null, new { onclick = "return NoDetailsDialog('" + #item.NoDetailReason + "')" });
}
return null;
}
),
grid.Column(
header: "Price Alt UOM",
format: #<text>#Html.FormatToDecimals((decimal)item.PriceInOrderUOM, (int)item.Numdecimals) / #item.OrderUOM </text>
),
grid.Column("Rolling12", "Rolling 12 Sales", format: #<text>#String.Format("{0:c0}", #item.Rolling12) </text>),
grid.Column("CMPercent", "Net CM ", format: #<text>#String.Format("{0:0.00} %", #item.CMPercent * 100) </text>)
))
</div>
</div>
<script type="text/javascript">
function NoDetailsDialog(message) {
alert(message);
return false;
}
</script>
You can use datatables. Please let me know how you progress with datatables and I can be available to help you through it,
I can even assist with razor syntax:
nuget DataTabes.net jquery plugin
bundles.Add(new StyleBundle("~/Content/CssGrid").Include(
"~/Content/DataTables/css/jquery.dataTables.min.css"));
bundles.Add(new ScriptBundle("~/bundles/JSGrid").Include(
"~/Scripts/DataTables/jquery.dataTables.min.js"));
JavaScript:
//perform tasks like initialize fields, show popup, and post to server
function DeleteMe()
function EditMe()
function Add()
Page:
$(document).ready(function() {
$('#theDataTable').DataTable();
} );
</script>
//button to show popup for add/edit here
<table id="theDataTable" class="display table table-striped table-bordered">
<thead>
<tr>
<th>Field Name A
</th>
<th>Field Name B
</th>
<th>Field Name C
</th>
</th>
<th>Delete
</th>
<th>Edit
</th>
</thead>
<tbody>
<% int rowCount = 0;
foreach (AClass item in Model.AClassList)
{ %>
<tr id="<%:rowCount%>">
<td><%:item.FieldA%></td>
<td><%:item.FieldB%></td>
<td><%:item.FieldC%></td>
<td>
<a href="#" title="Delete" class="btn btn-default btn-xs btn-block"
onclick="return DeleteMe('<%:item.Id%>')">Delete</a>
</td>
<td>
<a href="#" title="Edit" class="btn btn-default btn-xs btn-block"
onclick="return EditMe('',
'<%:item.FieldA %>',
'<%: Html.Encode(item.FieldB) %>',
'<%: Html.Encode(item.FieldC) %>')">Edit</a>
</td>
<% rowCount++;
} %>
</tr>
</tbody>
</table>
I have come across the same problem before. In my case it ended up being something to do with the MVC view resolver being scoped to the wrong folder due to calling a different controller than the one that had been used to construct the view which I was making the call in.
I know that's not much help, and it does seem peculiar as you have explicitly stated the controller name in your BeginForm statement. I had my mentor resolve the issue for me in the end, he did so by trial and error just commenting out the various lines until the problem was isolated.

ng-table get data from rails api not working

I'm trying to make a simple table with pagination by using Angularjs ng-table.
I included the js and css files to my rails 3 layout. When page first loaded, it displays a table then fires a http get to rails controller to get json(it works fine until this point).
What I'm trying to do is add pagination to my table.
I received error "angular is not defined" and there is no request from http get to rails controller. Please show me what I'm doing wrong here.
Thank you
(function(){
var app = angular.module("apTags", ["ngTable"])
// call back after table finished ng-repeat
.directive('onFinishRender', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
tableResponsiveAdjustHeight();
});
}
}
}
});
app.controller("apTagsController", [ "$http", function($scope, ngTableParams, $http){
// table has empty data when page first loaded
var apTags = this;
apTags.tags = [];
// Then it fires a http get to rails api to get data and append to table
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10 // count per page
}, {
total: data.length, // length of data
getData: function($defer, params) {
$http.get("ap_tags.json", {params: { api: true, page: params.page() } }).success(function(data){
apTags.tags = data;
$defer.resolve(data.slice((params.page() - 1) * params.count(), params.page() * params.count()));
});
}
});
}]);
})();
<div class="container" ng-app="apTags">
<div ng-controller="apTagsController as list">
<p><strong>Page:</strong> {{tableParams.page()}}</p>
<p><strong>Count per page:</strong> {{tableParams.count()}}</p>
<table ng-table="tableParams" id="table_tags" class="table table-condensed table-bordered table-hover">
<tr ng-repeat="tag in list.tags" on-finish-render="ngRepeatFinished">
<td data-title="'Tag'">{{tag.name}}</td>
<td data-title="'Share'">{{tag.share}}%</td>
<td data-title="'Direct Product Count'"></td>
</tr>
</table>
</div>
</div>

Binding backbone collection to view and underscore template on front end

I am using backbone + jquery mobile and couldn't get my array of models (collections) to output to the UI via underscore template.
My model is as follows:
var shortcake = Backbone.Model.extend({
defaults: function() {
return {
name: "No Slot",
butter: false,
time: "3pm",
icon: "plus",
deladd: "ADD"
};
},
initialize: function() {
this.bind("change:butter", function(){
if (this.model.butter == false) {
this.set({name: this.defaults.name});
};
}),
}
});
My collection is as follows:
var shortcakes = Backbone.Collection.extend ({
model: shortcake
});
var shortcake1 = new shortcake({ name: "How Bizarre", butter: "true", time: "1", icon:"plus", deladd:"ADD" });
var shortcake2 = new shortcake({ name: "Sexual Healing", butter: "true", time: "1", icon:"plus", deladd:"ADD" });
var shortcakeAlbum = new shortcakes([ shortcake1, shortcake2]);
And my view:
var shortcakeUI = Backbone.View.extend ({
tagName: "li",
template: _.template($('#shortcakeTemplate').html()),
initialize: function(){
this.render();
},
render: function() {
var variables = { namee: name };
if (this.model.butter == false) {
this.model.deladd = "ADD";
this.model.icon= "plus";
this.el.html( template );
}
else {
this.model.deladd = "DELETE";
this.model.icon= "minus";
this.el.html( template );
}
},
)};
var ShortcakeUI = new shortcakeUI({
collection : shortcakeAlbum,
el: $("#shortcakeinterface")[0]
});
ShortcakeUI.render();
And my html is:
<ul data-role="listview" data-split-icon="gear" data-split-theme="d">
<div id="shortcakeinterface"></div>
</ul>
<!---Templates--->
<script id="shortcakeTemplate" type="text/template">
<% for(var i = 0; i < shortcakeAlbum.length; i++){ %>
<% var shortcakez = shortcakeAlbum[i]; %>
<fieldset class="ui-grid-a">
<div class="ui-block-a">
<h3><%= shortcakez.time %></h3>
<p><%= shortcakez.name %></p>
</div>
<div class="ui-block-b">
<div id="8" data-role="controlgroup" data-type="horizontal" >
<%= shortcakez.deladd %>
Test
</div>
</div>
</fieldset>
<% } %>
</script>
So with these, my UI does not show the list of models on load.
Just starting out on backbone and js, am I doing things right here?
You need to pass the model to your template in render().
Instead of
this.el.html( template );
do this
$(this.el).html( this.template(this.model.toJSON()) );

Jquery form post Issues

I am using asp.net MVC and I am having an issue posting a form using jquery.
It is not posting to the url I am telling it to.
If I use firebug, it shows the post happening but it is posting to the index of the controller everytime. I cannot figure out why. I have verified the url of the action I am trying to post but I can't figure out why it is always posting to the index of the controller....Note: the view in which the form is found IS the index view. so Basically it is posting to it's own action rather than the one in the url i am telling it to. Any help would be great. thanks!
here is my form
<form action='' id="descriptionForm">
<%=Html.Hidden("claimNumber", ViewData["claimNumber"])%>
<%=Html.Hidden("partNumber", ViewData["partNumber"])%>
<%=Html.Hidden("qty", ViewData["qty"])%>
<table>
<tr>
<td style="text-align: right">
Category:
</td>
<td>
<%=Html.DropDownList("problemCategory", (IEnumerable<SelectListItem>)ViewData["problemSelect"], "-Select-")%>
</td>
</tr>
<tr>
<td style="text-align: right">
Details:
</td>
<td>
<select id="problemDetails">
</select>
</td>
</tr>
<tr>
<td style="text-align: right">
Dealer Notes:
</td>
<td>
<%=Html.TextArea("dealerNotes", "", 3, 40, null)%>
</td>
</tr>
</table>
<div style="position: absolute; bottom: 8px; right: 8px">
<input type="button" id="itemDetailsCancel" value="Cancel" />
<input type="submit" id="itemDetailsSubmit" value="Save" />
</div>
</form>
<a href='<%=ResolveUrl("~/Warranty/WarrantyClaims/CompleteAddLineItemToClaim/") %>'
id="CompleteLineItemUrl"></a>
Here is my Javascript
$("#descriptionForm").submit(function () {
var completeurl = $("#CompleteLineItemUrl").attr('href');
var data = $(this).serialize();
$.post({
type:'POST',
url: completeurl,
data: data,
success: function (result) {
alert("done");
}
});
return false
});
and just for good measure here is the controller action I am trying to post to(though it doesn't do much yet)
[HttpPost]
public ActionResult CompleteAddLineItemToClaim(string claimNumber, string partNumber, string qty, string problemCategory, string problemDetails, string dealerNotes)
{
var result = new { result = "done" };
return Json(result, JsonRequestBehavior.AllowGet);
}
Update:
updated javascript
$(function(){
$('#descriptionForm').submit(function () {
var completeurl = $('#CompleteLineItemUrl').attr('href');
var data = $(this).serialize();
$.ajax({
type: 'POST',
url: completeurl,
data: data,
success: function (result) {
alert('done');
}
});
return false;
});
});
Is the form itself loaded by an ajax call?
If so you need to use the live() function of jquery.
Make sure you have wrapped your javascript in a document.ready before subscribing for any events. Also you have a missing ; when returning false at the end of your method.
But your real problem is that you want to use $.ajax instead of $.post. So what actually happens is that you are getting a javascript error because of wrongly using the $.post function and the .submit handler never has time to return false and cancel the default submission of the form and the browser happily proceeds into POSTing to the action of the form (which is empty and default to the action that rendered this form).
So to sum up:
$(function() {
$('#descriptionForm').submit(function () {
var completeurl = $('#CompleteLineItemUrl').attr('href');
var data = $(this).serialize();
$.ajax({
type: 'POST',
url: completeurl,
data: data,
success: function (result) {
alert('done');
}
});
return false;
});
});
Or if you wanted to use $.post:
$(function() {
$('#descriptionForm').submit(function () {
var completeurl = $('#CompleteLineItemUrl').attr('href');
var data = $(this).serialize();
$.post(completeurl, data, function (result) {
alert('done');
});
return false;
});
});
Also instead of generating links à la classic WebForms way:
In ASP.NET MVC you use HTML helpers in order to ensure that link urls are conform to your routes:
<%= Html.ActionLink(
"Link text",
"CompleteAddLineItemToClaim",
"WarrantyClaims",
new { area = "Warranty" },
new { id = "CompleteLineItemUrl" }
) %>

Resources