Knockout.js code seems to be working intermittently - model-view-controller

We use Knockout.js and MVC in a Webapp and are having an issue, where the order merchandise total observed is 0 by Knockout.js, as displayed in the GUI.
The code seems to be working intermittently, because sometimes we do show the merchandise total in other orders. All orders use the same code and a merchandise total non zero value is always seen in the
OrderDetailClientViewModel object within the controller before being passed to the view. The view is coded in Knockout.js and plain javascript.
The "Totals" property shown below is an object (Models.OrderTotalViewModel), which contains the "MerchandiseTotal" field, which is sometimes showing a 0. I'm showing the relevant parts of the two view files below. I don't see the merchandiseTotal value being modified erroneously in the code. Only helpful segments are shown below.
Any suggestions to fix this intermittent behavior would be greatly appreciated!!!
Thank you,
Ken
--Edit.cshtml
#model Models.OrderEditPageViewModel
...
var rawViewModel = #(Html.ToJson(Model.OrderDetailClientViewModel()));
var viewModel = ko.mapping.fromJS(rawViewModel,
{
'HeaderData': {
create: function(options) {
options.data.StartDate = new Date(options.data.StartDate);
options.data.EndDate = new Date(options.data.EndDate);
var headerData = ko.mapping.fromJS(options.data);
headerData.errors = new HeaderDataError();
return headerData;
}
},
'Totals': {
create: function(options) {
var totals = ko.mapping.fromJS(options.data);
totals.errors = new TotalsError();
totals.isPromoCodeApplied = ko.observable(false);
if ($.trim(totals.PromoCode()) !== "")
totals.isPromoCodeApplied(true);
return totals;
}
}
});
...
-- This segment in Edit.cshtml shows where the OrderTotalViewModel.cshtml is called for Totals.
<tr>
<td colspan="3">
#Html.EditorFor(m => m.Totals)
</td>
</tr>
--OrderTotalViewModel.cshtml
#model Models.OrderTotalViewModel
#{ Layout = null; }
...
<td colspan="3" style="text-align:right">
<table class="PaddedTable" style="width:925px">
<tbody>
<tr>
<td style="width:125px;text-align:right">Merchandise Total:</td>
<td style="text-align:right" class="NormalTextBold">
#(Html.Knockout().SpanFor(m => m.MerchandiseTotal)
.HtmlAttributes(new { #class = "NormalTextBold" })
.Currency())

Related

Pagination and sorting in Spring MVC 4

I'm building a web app using spring mvc 4, thymeleaf and mysql (jdbc is used not hibernate or JPA) .. and I'm trying to do pagination and sorting, but I think I have a problem understanding it.
When I search for pagination using spring mvc all I can find is PagedListHolder and MutableSortDefinition, but I don't think it's the right way to go since it will load a list of all the data in server memory for each request, is that right? and if so, then what is the best way to implement pagination and sorting given that there are hundreds of thousands of records (advertisements for real-estate over a month, with almost 2500 ads a day)
So, could someone put a real-world example of how to implement pagination and sorting in a way that can be used with large data apps?
Try this way :
findAll method with argument "PageRequest()" provides the server side pagination
there are two methods
PageRequest(int page, int size)
PageRequest(int page, int size, Direction direction, String... properties)
View :
<table class="table">
<thead style="background-color: #eee">
<tr>
<td>Dispature</td>
<td>Service</td>
<td>Host</td>
<td>Value</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in app.metricsList">
<td>{{x.dispature}}</td>
<td>{{x.service}}</td>
<td>{{x.host}}</td>
<td>{{x.value}}</td>
</tr>
</tbody>
</table>
<div align="center">
<uib-pagination items-per-page="app.itemPerPage" num-pages="numPages"
total-items="app.totalItems" boundary-link-numbers="true"
ng-model="app.currentPage" rotate="false" max-size="app.maxSize"
class="pagination-sm" boundary-links="true"
ng-click="app.getPagableRecords()"></uib-pagination>
<div style="float: right; margin: 15px">
<pre>Page: {{app.currentPage}} / {{numPages}}</pre>
</div>
</div>
Js Controller :
app.controller('AllEntryCtrl',['$scope','$http','$timeout','$rootScope', function($scope,$http,$timeout,$rootScope){
var app = this;
app.currentPage = 1;
app.maxSize = 5;
app.itemPerPage = 5;
app.totalItems = 0;
app.countRecords = function() {
$http.get("countRecord")
.success(function(data,status,headers,config){
app.totalItems = data;
})
.error(function(data,status,header,config){
console.log(data);
});
};
app.getPagableRecords = function() {
var param = {
page : app.currentPage,
size : app.itemPerPage
};
$http.get("allRecordPagination",{params : param})
.success(function(data,status,headers,config){
app.metricsList = data.content;
})
.error(function(data,status,header,config){
console.log(data);
});
};
app.countRecords();
app.getPagableRecords();
}]);
Controller :
#RestController
public class HomeController {
#Autowired
private HomeRepo repo;
#RequestMapping(value = "allRecordPagination", method = RequestMethod.GET)
public Page<Metrics> getAllRecordPagination(#RequestParam("page") int page, #RequestParam("size") int size){
return repo.findAll(new PageRequest(page-1, size));
}
}
Repository :
#Repository
public interface HomeRepo extends JpaRepository<Table, String>{
}
In order to expand my comments I want to share some code snippets to show how easy it is to implement Dandelion Datatables with Thymeleaf.
So, on the client side I have two files: html for table render
....
<table id="dTable" class="display dataTable" dt:table="true">
<thead>
<tr>
<th th:text="#{requestId}"></th>
<th th:text="#{clientTime}"></th>
<th th:text="#{requestDate}"></th>
<th th:text="#{receiver}"></th>
</tr>
</thead>
</table>
....
and js for table initialization
$(document).ready(function() {
$('#dTable').DataTable( {
ajax: { url: "/bhost/dtable_list"},
processing: true,
serverSide: true,
bFilter: false,
columns: [
{ data: "requestId" },
{ data: "clientTime" },
{ data: "requestDate" },
{ data: "receiver", orderable: false },
],
lengthMenu: [50, 100, 200, 500],
language: {
thousands: " "
}
} );
} );
Even though it's possible to configure dandelion datatables only in html I prefer to use JQuery way to do it, since it's more flexible.
On the server side we used our own created database access layer (not quite useful to share it) and dandelion DatatablesCriterias class to get current state of table (current page index, page length, selected sorted column etc.)
Controller
....
#RequestMapping(value = "/dtable_list")
#ResponseBody
public DatatablesResponse<DataDTO> getTableData(HttpServletRequest request) {
HttpSession session = request.getSession();
DataModel model = (DaatModel) session.getAttribute(MODEL_NAME);
DatatablesCriterias criterias = DatatablesCriterias.getFromRequest(request);
List<DataDTO> list = finder.getForCriterias(model, timeZoneOffset, criterias);
Long totalCount = model.getCount();
return DatatablesResponse.build(new DataSet<>(list, totalCount, totalCount), criterias);
}
....
The key feature here is DatatablesCriterias, since it contains all necessary data to retrieve entries that correlate with user selection.
And that's pretty much it (Except configuration part, I guess)
this is an example of pagination with SpringBoot and Thymeleaf templates, try it!!
clone it and run it

Access Html.ActionLink property in Controller file

I need to access practiceid property in my controller file please help how I can access this
Corporate
Tax & Employee Comp/Exec Benefits
Business Finance & Restructuring
Regulatory
My csHtml code is as follows:
#foreach (var facetData in Model.SearchResultItems.Facets.Select((x) => new { Item = x.Key, Index = x.Value }))
{
<tr>
<td>
#Html.ActionLink(#facetData.Index, "Search","Search", new { practiceid = #facetData.Item })
</td>
</tr>
}
and controller code is as follows:
public ActionResult Search(string practiceid)
{
}
But I'm not getting anything in my practiceid parameter.
See this question.
What you want to do is to add parameters to the tag, not to the link. Which means you should leave fourth argument null and use fifth instead. ie.
#Html.ActionLink(#facetData.Index, "Search","Search", null, new { practiceid = facetData.Item })
And the documentation for this helper method with focus on fifth parameter.
Add the extra null
#foreach (var facetData in Model.SearchResultItems.Facets.Select((x) => new { Item = x.Key, Index = x.Value }))
{
<tr>
<td>
#Html.ActionLink(#facetData.Index, "Search","Search", new { practiceid = facetData.Item }, null)
</td>
</tr>
}

How to POST to database through URL

I'm writing a web application in Spring/Hibernate that handles basic voting functionality. I want to have a link to /vote/{gameId} which will add that vote to the database for that specific ID. I'm really at a loss as for how to accomplish this though. Here's what I've tried in my controller:
#RequestMapping(value="/vote/{gameId}", method = RequestMethod.POST)
public String addVote(#PathVariable("gameId")
Integer gameId) {
Vote vote = new Vote();
vote.setGameId(gameId);
voteService.addVote(vote);
return "redirect:/games/wanted.html";
}
Here's where the link shows up in a jsp:
<c:if test="${!empty games}">
<table>
<tr>
<th>Game Title</th>
<th>Votes</th>
<th> </th>
</tr>
<c:forEach items="${games}" var="game">
<tr>
<td><c:out value="${game.title}"/></td>
<td>Placeholder</td>
<td>Vote!</td>
</tr>
</c:forEach>
</table>
</c:if>
When I try this though I just get a 404 error. Any insight would be great.
This is how you make a post call with plain Javascript:
var url = "vote";
var params = "id=1";
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(params);
You need to call this in the onclick of your link.
On the other hand it is a lot easier if, for example, you use the jQuery Javascript library:
For your particular case it would be something like:
$.post("vote", { id: "1" } );
Or the full jQuery answer (remember to replace #linkid with the id of you tag):
$(document).ready(function() { //this runs on page load
// Handler for .ready() called.
$('#linkid').click(function(event) { //this finds your <a> and sets the onclick, you can also search by css class by type of tag
$.post("vote", { id: "1" } );
return false; //this is important so that the link is not followed
});
});

Can't set SelectedItem in DropDownList in my MVC3 view

I know that I can set the SelectedItem in my controller, but I can't figure out how to set it in my view. I'm working on a sort of flashcard (study guide) application and I have imported about 400 test questions. Now I want to write a page for the instructor to be able to select a "Category" for each question. I'd like them to be able to update the category for all the questions on one page. My model has a question entity that contains a foreign key field to the category entity (the field is called QuestionCategory). So, my view is based on the Question entity, but I'm sending over the list of Categories (there are 14) in the ViewBag (so I don't have to send a full SelectList over with each of the 400 questions. As my view is iterating thru the items in my View, I just want to add a SelectList that contains the 14 categories in my ViewBag and then set the SelectedItem based on the value of item.QuestionCategory. I can't make it work.
Here's my controller action:
public ActionResult Index()
{
var context = new HBModel.HBEntities();
var query = from q in context.tblQuestions.Include("tblCategory") select q;
var questions = query.ToList();
ViewBag.Categories = new SelectList(context.tblCategories, "CategoryID", "CategoryName");
return View(questions);
}
Here's some of the things I've tried in the view (with associated error messages in the comments)
#model IEnumerable<HBModel.tblQuestion>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Question
</th>
<th>
Answer
</th>
<th>
AnswerSource
</th>
<th>
Category
</th>
<th>
Action
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#item.Question
</td>
<td>
#item.Answer
</td>
<td>
#item.AnswerSource
</td>
<td>
#item.tblCategory.CategoryName
#*This one works, but cannot initialize the selected item to be current database value*#
#Html.DropDownList("Categories")
#*compile error - CS0200: Property or indexer 'System.Web.Mvc.SelectList.SelectedValue' cannot be assigned to -- it is read only*#
#*#Html.DropDownListFor(m => item.QuestionCategory, (ViewBag.Categories as SelectList).SelectedValue = item.QuestionCategory)*#
#*error {"DataBinding: 'System.Web.Mvc.SelectListItem' does not contain a property with the name 'CategoryId'."}*#
#Html.DropDownListFor(m => item.QuestionCategory, new SelectList(ViewBag.Categories, "CategoryId", "CategoryName"))
#*error - {"DataBinding: 'System.Char' does not contain a property with the name 'CategoryId'."}*#
#Html.DropDownListFor(m => item.QuestionCategory, new SelectList("Categories", "CategoryId", "CategoryName"))
)
</td>
<td style="width: 100px">
#Html.ActionLink("Edit", "Edit", new { id = item.QuestionID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.QuestionID })
</td>
</tr>
}
</table>
Of course, if I can get this to work, I'll need to try and add an action to go back to the controller and update all the records, but I'll just be happy to resolve my current issue.
I would really appreciate any help on this - Thanks!
You need to explicitly create the options in the select tag, using #Html.DropDownList, as follows (taken from a working app):
#Html.DropDownListFor(model => model.IdAccountFrom, ((IEnumerable<FlatAdmin.Domain.Entities.Account>)ViewBag.AllAccounts).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.AccountName),
Value = option.AccountId.ToString(),
Selected = (Model != null) && (option.AccountId == Model.IdAccountFrom)
}), "Choose...")
#Html.ValidationMessageFor(model => model.IdAccountFrom)
You obviously need to change to the properties on your #Model.
NOTE:
This code was auto-generated by the MvcScaffolding NuGet package when I scaffolded a controller.
This package requires you to use Entity Framework Code First POCO classes for your entities. These are easy to generate from an existing database using the Entity Framework Power Tools CTP.
With MVC, you need to spend some time researching the tooling that is out there to help you generate the stuff that you need. Using these tools is a great way to get started and to see how to do things. You can then tweak the output to your heart's content.

How can I reference MVC item/model in HTMLAttributes?

I'm trying to list two radio buttons in each row of a table, but I haven't been able to assign unique IDs to each radio button. I'd like to assign the IDs based on the #item.myID as follows:
#foreach (var item in Model)
{
<tr>
<td>
#Html.RadioButton("Yes", #item.myID, #item.IsCool, new { id = "#item.myID", autopostback = "true" })
#Html.RadioButton("No", #item.myID, !#item.IsCool, new { id = "#item.myID", autopostback = "true" })
</td>
</tr>
}
However, the IDs keep rendering literally as "#item.myID". In other words, it's not treating the # sign as a special character. I've also tried using parenthesis, like this: "#(item.myID)".
You need to remove the quotes from around the id assignment, like so;
#foreach (var item in Model)
{
<tr>
<td>
#Html.RadioButton("Yes", item.myID, item.IsCool, new { id = item.myID, autopostback = "true" })
#Html.RadioButton("No", item.myID, !item.IsCool, new { id = item.myID, autopostback = "true" })
</td>
</tr>
}
Also, note that you don't need the additional "#" symbol when you are already in the context of another Razor code block - the Razor View Engine is pretty clever :)

Resources