Checkbox (model) dosn't change value when checked - c#

Ive made some checkboxes in a View. The checkboxes is implemented via the ViewModel with bool properties. I'm currently trying to change a query in the controller to "date" or "month" depending if the checkbox has been checked. However in the Controller it always jumps the the "else statement" even if "Month" has been checked. Month is always False.
I suspect the JavaScript code might be wrong.
This User Interface:
In my Controller method i try to do the following:
Controller:
var request = GoogleAnalyticsService.Data.Ga.Get("ga:59380223", start, end, "ga:visitors");
var request = GoogleAnalyticsService.Data.Ga.Get("ga:59380223", start, end, "ga:visitors");
if (model.Month)
{
request.Dimensions = "ga:month";
request.Sort = "-ga:month";
}
else
{
request.Dimensions = "ga:date";
request.Sort = "-ga:date";
}
request.MaxResults = 10000;
Google.Apis.Analytics.v3.Data.GaData d = request.Execute();
In The view ive implemented my Viewmodel and tried writing some javascript checking if what checkbox have ´been checked and if to return true or false:
View:
<table class="adminContent">
<tr>
<td class="adminTitle">
#Html.NopLabelFor(model => model.StartDate):
</td>
<td class="adminData">
#Html.EditorFor(model => model.StartDate)
</td>
</tr>
<tr>
<td class="adminTitle">
#Html.NopLabelFor(model => model.EndDate):
</td>
<td class="adminData">
#Html.EditorFor(model => model.EndDate)
</td>
</tr>
<tr>
<td class="data" colspan="2">
#Html.CheckBoxFor(model => model.Date, new { id = "Day" }) // -- Checkbox Date
#Html.LabelFor(model => model.Date)
</td>
</tr>
<tr>
<tr>
<td class="data" colspan="2">
#Html.CheckBox("chkMonth", new { #onclick = "updatemyhidden(this)" }) // -- Checkbox Month
#Html.HiddenFor(model => model.Month, new { id = "Month" })
#Html.LabelFor(model => model.Month)
</td>
</tr>
</tr>
<tr>
<td class="adminTitle">
#Html.NopLabelFor(model => model.GAStatisticsId ):
</td>
<td class="adminData">
#Html.DropDownList("GAStatisticsId", Model.AvailableGAStatistics)
<input type="button" id="GAStatisticsReport-Submit" class="t-button" value="#T("Admin.Common.Search")" />
</tr>
</table>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="/Scripts/jquery.min.js"></script>
<script type="text/javascript">
$("#GAStatisticsReport-Submit").click(function () {
if ($("select[name='GAStatisticsId'] option:selected").text() == "Visitors Report")
drawChartVisitors()
if ($("select[name='GAStatisticsId'] option:selected").text() == "Orders Report")
drawChartOrders()
if ($("select[name='GAStatisticsId'] option:selected").text() == "Conversion Report")
drawConversion()
function updatemyhidden(chkbox) {
$("#Month").val(chkbox.checked);
}
})
google.load("visualization", "1", { packages: ["corechart"] });
google.load("visualization", "1", { packages: ["treemap"] });
function drawChartVisitors() {
$.get('/GAStatistics/GetVisitors', {
StartDate: $('##Html.FieldIdFor(model => model.StartDate)').val(),
EndDate: $('##Html.FieldIdFor(model => model.EndDate)').val(),
},
function (data) {
var tdata = new google.visualization.DataTable();
tdata.addColumn('date', 'Date');
tdata.addColumn('number', 'Visitors');
for (var i = 0; i < data.length; i++) {
if ($("#Month").is(":checked")) {
var dateStr = data[i].Date.substr(0, 4);
}
else {
var dateStr = data[i].Date.substr(0, 4) + "-" + data[i].Date.substr(4, 2) + "-" + data[i].Date.substr(6, 2);
}
tdata.addRow([new Date(dateStr), parseInt(data[i].Visitors)]);
}
The if-statements in the controller dosnt seem to operate depending on what i select in the view.
Note: im not using httpPost/get as the data is loaded with Google Charts and i don't want the whole page to re-aload each time a new request is selected.

Is because you set bool field on the month so it will rendered as true/false for your checkbox. You have a look at the rendered HTML for the month checkbox., and no matter you checked or not the data still send back to server as true/false depend what been set when rendering the page. This value will never change.
So i suggest you either add one more property in your viewmodel to keep try check/unchecked state and in the view rendered it as hidden field and update this hidden field whenever checkbox is ticked/unticked.
Or the month field render as hidden field and add one more checkbox in the page to update the month field when checkbox is checked/unchecked
Let say we use 2nd approach, the code will look something like this, (I did not test the code below). I hope this helps:
#Html.CheckBox("chkMonth", new { #onclick = "updatemyhidden(this)" })
#Html.HiddenFor(model => model.Month)
<script type="text/javascript">
function updatemyhidden(chkbox) {
$("#Month").val(chkbox.checked);
}
</script>

Related

ASP.NET MVC - Open Table in new window and print

I'm using ASP.NET MVC and have a table with 9 columns which shows results from the database where the user can filter values based on columns. The table structure looks like this:
<table class="tableMain" id="x">
<thead>
<tr class="trMain">
<th class="thMain">
#Html.DisplayNameFor(model => model.ID)
</th>
<th class="thMain">
#Html.DisplayNameFor(model => model.YEAR)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr class="trMain">
<td class="tdMain">
#Html.DisplayFor(modelItem => item.ID)
</td>
<td class="tdMain">
#Html.DisplayFor(modelItem => item.YEAR)
</td>
<td class="tdMain">
<input type="checkbox" class="chkCheckBoxId" name="airlineId" value="#item.ID" />
</td>
<td class="tdMain">
#Html.ActionLink("EditValue", "Edit", new { id = item.ID })
</td>
</tr>
}
</tbody>
</table>
Now I need a button, so that the dynamically generated table opens in a new window and the print dialog opens automatically. I had this piece of code:
<div class="line-btn">
<input type="submit" value="print" onclick="printTable()" class="btn fl btn-print">
</div>
<script language="javascript">
function printTable()
{
var printContent = document.getElementById("x");
var windowUrl = 'about:blank';
var num;
var uniqueName = new Date();
var windowName = 'Print' + uniqueName.getTime();var printWindow = window.open(num, windowName, 'left=50000,top=50000,width=0,height=0');
printWindow.document.write(printContent.innerHTML);
printWindow.document.close();
printWindow.focus();
printWindow.print();
printWindow.close();
}
</script>
The problem here is that the table is completely unsorted when printed so the rows/columns are shifted.
I found this example:
https://datatables.net/extensions/buttons/examples/print/simple.html
This is exactly what I need (open the table in a new window and open print dialog). But unfortunately this sample has a lot of code in the javascript files that I don't need. There is a search field included and a pagination.
Can someone help me please? Thank you very much!
Ok I found a good solution.
This is the code I used:
<script src="#Url.Content("~/Scripts/jquery-3.5.1.js")" type="text/javascript"></script>
<script>
var myApp;
myApp = (function (app) {
$('#x').click(function () {
myApp.print();
});
app.print = function () {
$.ajax({
url: 'Home/Print',
success: function (data) {
if (myApp.arePopupsBlocked()) {
alert('please allow popups.');
}
var printWindow = window.open();
if (printWindow) {
$(printWindow.document.body).html(data);
} else {
alert('please allow popups.');
}
},
error: function () {
alert('Error');
}
});
};
app.arePopupsBlocked = function () {
var aWindow = window.open(null, "", "width=1,height=1");
try {
aWindow.close();
return false;
} catch (e) {
return true;
}
};
return app;
})(window.myApp || {})
</script>
and right before the table-tag the link to click:
<style>
/* suppress link for printing */
##media only print {
a {
display: none;
}
}
</style>
[print table]
There opens no new window but the table is well formated for printing.

How to properly reorder ids after exchange rows between tables (jQuery and ASP.NET MVC4)

I have here a view model which has two list objects. I will display them as two tables in my view. I've already created EditorFor for them. I'll place four buttons (move one right, move all right, move one left, move all left) for the exchange operations. I've googled everywhere and no goal on how to accomplish that, because I need to move the entire object, replace all "name" and "id" tags, reorder indexes and so on, because this way my lists will be posted correctly. I'm using Datatables.net and jQuery too.
Does anybody have a clue on how to do that?
Thank you in advance. The code goes below
EDIT
Since list elements on ASP.NET MVC are indexed like "ListName_0__Code"(for Id) and "ListName[0].Code" (for name) how to properly reorder these indexes?
EditorFor
#model ViewModels.UserPermissionDetails
<tr id="#Model.Id">
<td>
#Html.HiddenFor(m => m.Code)
#Html.HiddenFor(m => m.Login)
#Html.HiddenFor(m => m.Name)
#Html.HiddenFor(m => m.IdEmpUser)
#Html.DisplayFor(m => m.Code)
</td>
<td>#Html.DisplayFor(m => m.Login)</td>
<td>#Html.DisplayFor(m => m.Nome)</td>
</tr>
View
<table id="tbBlock">
<thead>
<tr>
<th>Code</th>
<th>Login</th>
<th>Name</th>
</tr>
</thead>
<tbody>
#Html.EditorFor(model => model.BlockList)
</tbody>
</table>
<table id="tbAllow">
<thead>
<tr>
<th>Code</th>
<th>Login</th>
<th>Name</th>
</tr>
</thead>
<tbody>
#Html.EditorFor(model => model.AllowList)
</tbody>
</table>
Exchange method (jQuery)
function addElement(OriginTableId, DestinyTableId, OriginListName, DestinyListName) {
var originTb = $(OriginTableId).DataTable(); //initialize DataTable.Net for origin table
var destinyTb = $(DestinyTableId).DataTable(); //initialize DataTable.Net for destiny table
var objectLine = $('#' + originTb.$('tr.selected').attr('id')); //get selected line that will be moved
//Name replacing code piece
var elementsFromLine = $(objectLine.children()[0]).children().toArray();
elementsFromLine.forEach(function (item, index, array) {
$(item).attr('id', $(item).attr('id').replace(OriginListName, DestinyListName)); //Replace 'OriginListName_0' with 'DestinyListName_0'
$(item).attr('name', $(item).attr('name').replace(OriginListName, DestinyListName)); //Replace 'OriginListName[0]' with 'DestinyListName[0]'
});
//Reordering code piece here, how to?
$(DestinyTableId + ' tbody').append(objectLine.clone(true, true));
objectLine.parent().remove();
}
It will be much easier for you to calculate and set the name values with the index only before you submit the form, not for every move action.
#Html.HiddenFor(m => m.Code, new { #class = "code" } })
// same for all the inputs you send to server
$("button[type='submit']").on("click", function (e) {
e.preventDefault();
updateIndexes();
$("form").submit();
});
function updateIndexes() {
$("#tbAllow").find("tbody").children("tr").each(function (i) {
var prefix = "BlockList[" + i + "].";
var $tr = $(this);
$tr.find("input.code").attr("name", prefix + "Code");
$tr.find("input.login").attr("name", prefix + "Login");
// same for all the inputs you send to server
});
};

MVC Get values from another form in the same View

The short and "straight" question:
A Controller action method (A) is called by a form with some parameters. In the same View, there is another form, which when submitted calls another action method (B) in the same controller.
How can I access the values of (B) form (but essentially they are the content values of dropdowns and textboxes) from the action method A?
The Long and winding explanation:
I have a View with two forms, like this:
using (Html.BeginForm("List", "Rapporti"))
{
<span>Ricerca Rapporti per Linea </span>
#Html.DropDownList("KLinea",
new SelectList(new RapportiCT.Domain.Entities.RapportiEntities().TLinea, "KLinea", "DLinea")
, "Scegli una linea");
<span>Data inizio</span>
#Html.TextBox("startDate", DateTime.Now.AddDays(-4).ToShortDateString(), new { #class = "dateTextBox" });
<span>Data fine</span>
#Html.TextBox("endDate", DateTime.Now.AddDays(-1).ToString("dd/MM/yyyy"), new { #class = "dateTextBox" })
<input type="submit" value="Cerca" />
}
if (Model.Count() > 0)
{
var lastArticolo = "";
<h2>Rapporti Capoturno #Model.First().rapportoCT.DLinea</h2>
<table>
#foreach (var rapporto in Model)
{
if (lastArticolo != rapporto.rapportoCT.DCodArt)
{
<tr>
<td class="td_title">
#rapporto.rapportoCT.DCodArt
</td>
<td colspan="3" class="td_title">
#rapporto.rapportoCT.DDescArt
</td>
<td class="td_title">
Rendimento
</td>
<td class="td_title">
#Pallet control.
</td>
<td class="td_title">
#Pallet accanton.
</td>
<td class="td_title">
Ore fermo linea
</td>
</tr>
lastArticolo = rapporto.rapportoCT.DCodArt;
}
using (Html.BeginForm("ControlloQualita", "Rapporti"))
{
<tr>
<td class="td_detail">
#rapporto.rapportoCT.Data
</td>
<td class="td_detail">
#rapporto.rapportoCT.Turno
</td>
<td class="td_detail">
#rapporto.rapportoCT.Lettera
</td>
<td class="td_detail">
#rapporto.rapportoCT.DNota
</td>
<td class="td_detail">
#rapporto.RendimentoLinea
</td>
<td class="td_detail">
#Html.TextBox("PalletControllati", rapporto.PalletControllati, new { style="width:50px" })
</td>
<td class="td_detail">
#Html.TextBox("PalletAccantonati", rapporto.PalletAccantonati, new { style = "width:50px" })
</td>
<td class="td_detail">
#Html.TextBox("OreFermoLinea", rapporto.OreFermoLinea, new { style = "width:50px" })
</td>
<td>
<input type="submit" value="Salva" />
</td>
</tr>
}
}
</table>
}
else
{
#:Nessun record trovato
}
Both forms post to the same RapportiController: the first form is used to query the database and show the resulting records, with the second one I'd like to update the database record.
View (snapshot):
So, my Controller class is like this:
// No problem here
public ViewResult List(int? KLinea = null, DateTime? startDate = null, DateTime? endDate = null)
{
IQueryable<VRapportiCT> qVRapporti = repository
.ViewRapporti(KLinea.Value, startDate.Value, endDate.Value);
List<VRapportiCT> lRapporti = qVRapporti.ToList();
List<RapportoRendimentoViewModel> listRRVM = new List<RapportoRendimentoViewModel>();
foreach (var rapporto in lRapporti)
{
RapportoRendimentoViewModel rrVM = new RapportoRendimentoViewModel();
rrVM.rapportoCT = rapporto;
rrVM.RendimentoLinea = repository.GetRendimentoLinea(rapporto);
rrVM.PalletControllati = "0";
rrVM.PalletAccantonati = "0";
rrVM.OreFermoLinea = "0";
listRRVM.Add(rrVM);
}
return View(listRRVM);
}
public RedirectToRouteResult ControlloQualita(int PalletControllati, int PalletAccantonati, int OreFermoLinea)
{
// How can I access the 1°form values here (a.k.a. the DropDown and Date text box values?
// ...Fake values, only to assert that the parameters get passed to the action...
RouteValueDictionary dic = new RouteValueDictionary();
dic.Add("KLinea", 55);
dic.Add("startDate", DateTime.Now.AddDays(-4));
dic.Add("endDate", DateTime.Now);
return RedirectToAction("List", "Rapporti", dic);
}
I see 2 options here:
Store last submitted "List" form in, lets say, Session, or TempData, or any other storage you like and restore these values on "ControlloQualita" form submission. This approch assumes that you need last submitted values from "List" form rather than latest.
Intercept "ControlloQualita" form submission in order to append values of "List" form to the request. This can be achieved with javascript by adding hidden inputs to the "ControlloQualita" form.

A checkbox to select / unselect them all

I want to create a checkbox that will have the "power" to check / uncheck a checkboxfor for each items presents in a list.
Here is part of the view as I built it right now (please bear with the false names and convention):
<p>
#using (Html.BeginForm("SendObj", "Manager"))
{
<p>
Select / UnSelet All Items #Html.CheckBox("selectAll", true)
</p>
<table id="objToSend">
<tr>
<th>Obj Name</th>
<th>Number In Stock</th>
(...)
</tr>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>#Html.DisplayFor(x => x[i].m_OthObj.m_ObjName)</td>
<td>#Html.DisplayFor(x => x[i].m_NbInStock)#Html.HiddenFor(x => x[i].m_NbInStock)</td>
(...)
<div id="divChckBox">
<td>
#Html.CheckBoxFor(x => x[i].m_IsSelected)
</td>
</div>
</tr>
}
</table>
<input type="submit" value="Send"/>
}
</p>
As for the "how", well, I have searched a bit around and I have tried this jquery script, but to no avail:
**** EDIT ****
Here's a new jQuery based on the comments people posted below. The alerts are there on debug purpose, and both appears when needed:
<script type="text/javascript">
$(document).ready(function() {
alert("The document is ready");
$("#selectAll").click(function() {
alert("The case has been clicked");
var chkValue = $(this).is(":checked");
$("#divChckBox").attr("checked", "checked");
});
});
</script>
I do not mind using jquery, far from it, I just do not know how it works yet. Maybe that's why what I have in mind does not work.
Can anyone help me out? Thank you!
* EDIT *
I will add here what the rendered page gives out for the checkboxes:
<td><input checked="checked" class="chckBoxList" data-val="true" data-val-required="The m_IsSelected field is required." name="[0].m_IsSelected" type="checkbox" value="true" /><input name="[0].m_IsSelected" type="hidden" value="false" /></td>
Maybe that will give out more informations on what's going on.
#Html.CheckBox("TheOneCheckBoxToRuleThemAll")
Change your current checkbox code to:
<td>#Html.CheckBoxFor(x => x[i].m_IsSelected, new{ #class = "checkGroup1"})</td>
The easiest Jquery ever (make sure to put it in document.ready like shown):
<script type="text/javascript">
$(document).ready(function () {
//alert("the document is ready");
$("#TheOneCheckBoxToRuleThemAll").click(function () {
//alert("inside my click event");
var chkValue = $(this).is(":checked");
$(".checkGroup1").prop("checked", chkValue);
});
});
</script>
EDIT:
My previous answer used the .attr() attribute. After testing, I had all sorts of trouble getting that to work. After referring to this SO post, I switched to using .prop() and everything magically began to function correctly.
Jquery .Attr()
Jquery .Prop()
EDIT:
In the example I've provided, your checkboxes MUST look like this:
<input name='itdoesnotmatter' id='donotcare' class='checkGroup1' />
also, do not use that stupid name that I put on there, use something easy like
#Html.CheckBox("MasterCheck")
I stand corrected: CheckBoxFor does NOT allow class setting
In your Helper
<div id="divChckBox">
#Html.CheckBoxFor(x => x[i].m_IsSelected)
</div>
And then make your selector group by the class:
$("#divChckBox :checkbox").attr("checked", "checked");
As there are MANY comments around and many answers, here's my current code (which works!):
<script type="text/javascript">
$(document).ready(function() {
//alert("The document is ready");
$("#selectAll").click(function() {
//alert("The case has been clicked");
var chkValue = $(this).is(":checked");
$(".divChckBox").prop("checked", chkValue);
});
});
</script>
<p>
#using (Html.BeginForm("SendObj", "Manager"))
{
<p>
Select / UnSelet All Items #Html.CheckBox("selectAll", true)
</p>
<table>
<tr>
<th>Card Name</th>
<th>Number In Stock</th>
(...)
</tr>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>#Html.DisplayFor(x => x[i].m_OthObj.m_ObjName)</td>
<td>#Html.DisplayFor(x => x[i].m_NbInStock)#Html.HiddenFor(x => x[i].m_NbInStock)</td>
(...)
<td>
<input type="checkbox" name="itdoesnotmatter" class="divChckBox" checked="true"/>
</td>
</tr>
}
</table>
<input type="submit" value="Send"/>
}
</p>
Now every checkboxes are checked or not depending on the state of the select all checkboxes! Thank you everyone.
Now I need to solve the problem of "unlinking" the result of the checkbox in my controller because a behavior was linked to this. But it's another problem.

ASP.NET MVC 3 NOT showing appropriate view, action called using jquery

I have a small problem.
My action is :
public ViewResult SearchForRooms(int HotelDDL)
{
List<Room> roomsInHotel = bl.ReturnRoomsPerHotel(HotelDDL);
return View(roomsInHotel);
}
Here is the jquery that is calling the action:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#HotelDDL").change(function () {
var text = $("#HotelDDL option:selected").text();
var value = $("#HotelDDL option:selected").val();
alert("Selected text=" + text + " Selected value= " + value);
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
});
});
});
</script>
And finally, here is the View that should be called:
#model IEnumerable<RoomReservation.Entities.Entities.Room>
#{
ViewBag.Title = "Search";
}
<h2>Result</h2>
<table>
<tr>
<th>
City
</th>
<th>
Hotel
</th>
<th>
Room label
</th>
<th>
Number of beds
</th>
<th>
Price per night
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelitem=>item.Hotel.City.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Hotel.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.NumberOfBeds)
</td>
<td>
#Html.DisplayFor(modelItem => item.PricePerNight)
</td>
</tr>
}
</table>
Everthing is working ok (databse return all rooms correctly) except final view rendering.
I have tried Phil's tool but it doesn't give me any suspicious hints:
RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
So, why is it not showing after jscript send it's post method to SearchForRooms()?
Thank you
P.S. If you need any other piece of code please just say so.
Note that doing an ajax post will not refresh or redirect the page like a classic post would.
The view is not showing because there is no where to place it. You post successfully, and return a view successfully but then do nothing with it. If you want to show the returned view, then you have to append it to the dom somehow. Here is a common method:
<div id="successDiv"></div>
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#HotelDDL").change(function () {
var text = $("#HotelDDL option:selected").text();
var value = $("#HotelDDL option:selected").val();
alert("Selected text=" + text + " Selected value= " + value);
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
}, function(result){//add callback for success - result is the returned view
$("#successDiv").html(result);//place the view inside of the div
});
});
});
</script>
Comment Response
#TunAntun - You should use a classic post if you want the view to have its own page. There is no way to accomplish this from ajax. You could do this with javascript though
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
}, function(result){//add callback for success - result is the returned view
$("#successDiv").html(result);//place the view inside of the div
});
would become
var postForm = document.createElement("form");
postForm.setAttribute("method","post");
postForm.setAttribute("action","/Home/SearchForRooms");
var postVal = document.createElement("input");
postVal.setAttribute("type","hidden");
postVal.setAttribute("name","HotelDDL");
postVal.setAttribute("value",$("#HotelDDL option:selected").val() );
postForm.appendChild(postVal);
document.body.appendChild(postForm);
$(postForm).submit();
This will dynamically issue the post you wanted. Then in your controller it will properly redirect or return a view. It is highly suggested that when returning a view from a [HttpPost] that you use RedirectToAction and then return the view from a [HttpGet] method in order to prevent refresh from reposting old data.

Categories

Resources