I'm working with in my first knockout experience and have been learning quite a bit. What I'm attempting to do is populate a new object and push it into the viewModel for display.
The select box ( drop down box) is populating but when I click on add, the object name is blank. Then it occurred to me, I have two fields I need to collect from to assemble the object so I'm not sure I'm going about this the right way....
My data model:
function Colors(data) {
this.ID = ko.observable(data.ID);
this.ColorName = ko.observable(data.ColorName);
this.Duration = ko.observable(data.Duration);
}
View:
<table id="NewColor">
<tbody>
<tr>
<td>
<select id="SelectColor" data-bind="options: AllColors, optionsText: 'ColorName', value: AllColorss.ID, optionsCaption: 'Select Color...'"></select>
<input id="Duration" data-bind="value: Duration" />
<button data-bind='click: addColor'>Add Color</button>
</td>
</tr>
</tbody>
The input ID="duration" isn't working / populating right but I'm working on getting the model data to update.... (This is a side issue I'll look at later so of there's syntax issues there, that's why)
The script to add from the button click:
self.addColor = function() { self.AddColors.push(new Color(NewColor )) };
When that runs, the ColorName is blank in the following table but a blank entry is added.
Display / update table:
<table>
<thead>
<tr>
<th padding: 10px; >Color</th>
<th padding: 10px; >Duration</th>
</tr>
</thead>
<tbody data-bind="foreach: AddColors">
<tr>
<td data-bind="text: ColorName"></td>
<td data-bind="text: Duration"></td>
<td>
<a href='#' data-bind='click: $parent.removeLine'>Remove</a>
</td>
</tr>
</tbody>
Is what I'm doing the way to add an object into the array for the newly created object? I don't see a SelectedColor.SelectedText or anything similar. How do I access the text property of the select drop down list?
I'm not sure if what I was doing before would work but I backed off what I had and added in the select box after the line was added which was the same thing the tutorial was doing. That worked. I can't thank you enough, Robert.
Related
I am currently trying to learn something about MVC by creating a small project. I already have managed to get a lot of things working, but now I am facing something I can not explain.
Basically, I have the usual setup (Model, Viewer, Controller) and my Model database is displayed in a View. Starting with the standard Create-View and -Action, which can be generated automatically in Visual Studio, I intended to change this method, so that some cells have calculated values and do not come from a user input.
This works fine for my Ready-column and Ready-Date-column, but fails for the Month-column. To generate a new row somehow
#Html.EditorFor(model => model.Month)
is needed. If I remove this (like I did for Ready and Ready-Date) clicking the submit-Button doesn't create anything and the application stays on the Create-Page.
My two ActionResults in the ModelController look like this:
public ActionResult Create()
{
//I use this in order to print the UpcomingMonth on the Create-Page
ViewBag.upcomingMonth = getUpcomingMonth();
return View();
}
public ActionResult Create([Bind(Include = "Report_ID,Month,Ready,Ready_Date")] Report report)
{
if (ModelState.IsValid)
{
//I would like to use this calculation for the Month-Value
report.Month = getUpcomingMonth();
//For Ready and Ready_Date it works to set the values here before adding to the db
report.Ready = true;
report.Ready_Date = System.DateTime.Now;
db.Reports.Add(report);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(report);
}
And the relevant part of my View:
<p style="float:right">
#*Button to create new month*#
#Html.ActionLink("Create", "Create")
</p>
<h2>Latest</h2>
<table class="table">
<thead>
<tr>
#*Column-header: Month*#
<th style="width: 10%; text-align:center">
#Html.DisplayNameFor(model => model.Month)
</th>
#*Column-header: True/False is ready*#
<th style="width: 10%; text-align:center">
#Html.DisplayNameFor(model => model.Ready)
</th>
#*Column-header: Set ready Date*#
<th style="width: 20%; text-align:center">
#Html.DisplayNameFor(model => model.Ready_Date)
</th>
</tr>
</thead>
<tbody>
<tr>
#*Cell: Latest Month*#
<td style="width: 10%; text-align:center">
#Html.DisplayFor(modelItem => Model.ElementAt(0).Month)
</td>
#*Cell: Latest True/False is ready
<td style="width: 10%; text-align:center">
...
</td>
#*Cell: Latest Set ready Date*#
<td style="width: 20%; text-align:center">
#Html.DisplayFor(modelItem => Model.ElementAt(0).Ready_Date)
</td>
</tr>
</tbody>
</table>
I really would appreciate any help!
PS: With ValidationSummary I get the following (no error message):
I think your view model doesn't validate. You can see what's error if you add these lines to view.
#Html.ValidationSummary(true, "Errors:", new { #class = "text-danger bg-danger" })
I finally found out what caused this behaviour.
In the setup of my model I defined a validation requirement, which did not allow an empty string. Because I set my data after I had checked ModelState.IsValid, the empty String did not pass this check and therefore the row wasn't added.
I solved it by removing the validation requirements of Month.
I am populating a razor table with a decent amount of data, but it takes > 10 minutes to load.
I am using a lot of logic in my view, and i know this isnt the best way to do this but this is what ive come up, as im new to razor.
names contains about 800 items, contacts 700, urls 3600, servers 1200
I dont think this is a lot but the way i am making the table is what i assume is holding up the application since i traverse these lists multiple times while within other ones.
Ive applied DataTables to this table, i thought it would help as limiting the rows show on the screen should mean the entire lists arent being traversed? Unless datatables still loads the entire table and just displays the 25. Is there a way to only load 100 results initially then slowly load the rest in over time?
Whats the best way to stop my app from hanging when creating this table
<table class="table table-responsive" id="result" data-page-length='25'>
<thead>
<tr>
<th>Application</th>
<th>Ministry</th>
<th>Contacts</th>
<th>Server</th>
<th>URL</th>
</tr>
</thead>
<tbody>
#foreach(var l in Model.names)
{
<tr>
<td style="width: 27%">
#Html.DisplayFor(modelItem => l.appName)
</td>
<td style="width:20%">
#Html.DisplayFor(modelItem => l.ministry)
</td>
<td style="width:20%">
#foreach (var k in Model.contacts)
{
if(k.appName == l.appName){#Html.Raw(k.contactName + " - " + k.contactRole + "<br>")}
}
</td>
<td colspan="2">
<table>
#foreach(var s in Model.servers)
{
<tr >
#if(s.appName == l.appName)
{
<td>
<p class="big">
#Html.Raw(s.server)
</p>
</td>
}
<td>
#foreach(var u in Model.filteredURls)
{
#if(u.appName == l.appName && u.server == s.server){#Html.Raw(u.url + "<br>")}
}
</td>
</tr>
}
</table>
</td>
</tr>
}
</tbody>
</table>
</div>
<script type="text/javascript" >
jQuery(document).ready(function () {
jQuery('#result').DataTable();
});
</script>
I have table
<table class="table table-hover">
<thead>
<tr>
<th>userid</th>
<th>image</th>
<th>name</th>
<th>family</th>
<th>level</th>
<th>fild</th>
<th>operation</th>
<th>up to next level</th>
</tr>
</thead>
<tbody>
#foreach (var item in StudentFunc.ShowAllStudents(Model.Class))
{
<tr>
<td>#item.studentid</td>
<td>
<img src="~/Image/StudentImage/#item.studntimage" width="60" height="60"/>
</td>
<td>#item.studentname</td>
<td>#item.studentfamily</td>
<td>#item.studentpayename</td>
<td>#item.studentreshtename</td>
<td>
<a onclick="Edit()" class="btn btn-primary click" href="#Url.Action("InsertScore", "Home", new {payeid = #item.PayeID, reshteid = #item.ReshteID, studentiD = #item.studentid, MostamarID = #StudentFunc.ShowStudents(item.studentid).MostamarID})"><span class="glyphicon glyphicon-pencil"><span style="font-family: 'B Titr'; margin-right: 10px;">ثبت نمره</span></span></a>
<a class="btn btn-default" href="#Url.Action("ListofScore", "Home", new {studentid = #item.studentid})"><span class="glyphicon glyphicon-list"><span style="font-family: 'B Titr'; margin-right: 10px;">لیست نمرات</span></span></a>
<a class="btn btn-default" href="#Url.Action("AddAbsent", "Home", new {studentid = #item.studentid})"><span class="glyphicon glyphicon-list"><span style="font-family: 'B Titr'; margin-right: 10px;"> ثبت غیبت</span></span></a>
</td>
<td>#Html.CheckBox("Pass", false)</td>
</tr>
}
</tbody>
</table>
in table I put a checkbox for select user for update level. Now how do I find what students selected and and how to send information about them to action?
One option is to put your code in a form and replace
#Html.CheckBox("Pass", false)
//with something like
#Html.CheckBoxFor(item => item.Pass)
and submit the form (you should be able to do this).
Or you can keep a list with student ids in javascript (add/remove a student id on check/uncheck) and send that list to server with an ajax call.
These are just some hints, you will have to try to write this code yourself.
Since you're iterating through the students the render the checkbox, I would suggest something like creating the checkboxes with a customer name that contains the student ID.
Replace
<td>#Html.CheckBox("Pass", false)</td>
with something like
<td>#Html.CheckBox("Pass_" + item.studentid)</td>
Now, in the controller action wherever you're posting these to, the Form Collection will contain all the selected checkbox names, and you can parse each one for "Pass_{StudentId}" to figure out which students were selected.
I have one following table html, the data of rows in the table is looped by foreach.
Can I use Razor to get the value of each row into a List or an array in C#?
My C# code Razor (I tried this so far)
#{
var l = new List<string>();
l.Add(#<input id="updated_value2" data-bind="value:value,visible:isEditing()" />);
}
Here's my table
<table class="table table-hover">
<tbody data-bind="foreach: $root.mapJsons(parameters())">
<tr class="data-hover">
<td>
<strong>
<span data-bind="text:key" />
</strong>
</td>
<td>
#*display label and input for dictionary<value> false DIS true APP*#
<input id="updated_value" data-bind="value:value,visible:isEditing()" />
<label id="display_value" data-bind="text:value,visible:!isEditing()" />
</td>
</tr>
</tbody>
<thead>
<tr>
<th style="width: 30%">
Name
</th>
<th style="width: 30%">
Value
</th>
<th></th>
</tr>
</thead>
</table>
Your foreach loop is being executed client-side (looks like a KnockoutJS binding?) rather than server-side, so any Razor code you embed in the table is only going to be called once as it's rendered by the server. So the answer is no, you cannot populate a server-side list with this particular foreach loop.
I've got a json list of objects I've populated into an observablearray([]). I know the data is there because of if I do this:
<table id="tblColors">
<thead>
<tr>
<th padding: 10px; >Color</th>
</tr>
</thead>
<tbody data-bind="foreach: AllColors">
<tr>
<td data-bind="text: ColorName"></td>
</tr>
</tbody>
The view shows all the colors.
However, when I do this:
<select data-bind="options: AllColors, optionsText: AllColors.ColorName,
value: AllColors.ID, optionsCaption: 'Select Color...'"></select>
I get the default "select color..." in the drop down box but each of the colors have [object Object]
I've tried optionsText: ColorName but the program stops and says JavaScript runtime error: 'ColorName' is undefined.
Try it like this
<select data-bind="options: AllColors, optionsText: 'ColorName', value: selectedColor, optionsCaption: 'Choose...'></select
Where the single quotes (') are the secret sauce.