I have a simple view with a checkbox at the bottom:
#model Application.Areas.Cms.Models.ProduktBeispielViewModel
#{
ViewBag.PopupHeadline = "Produktbeispiele";
ViewBag.PopupSubHeadline = Model.Item != null ? Model.Item.NameInCurrentLang : "";
ViewBag.HideLanguageComparison = true;
}
#section TabMenu
{
<ul>
<li>Einstellungen</li>
<li>Bild</li>
</ul>
}
<form action="#Url.Action("SaveIndex")" method="POST" id="idForm">
#Html.HiddenFor(m => m.AutoCloseWindow)
#Html.HiddenFor(m => m.Item.Id)
<checkbox/>
</form>
I have this Index:
public ActionResult Index(int id = 0, int categoryId = 0, bool autoclosewindow=false,bool refreshOpener=false)
{
var model = LoadModel(id, categoryId);
model.AutoCloseWindow = autoclosewindow;
model.RefreshSequenceInOverview = refreshOpener;
foreach (var lang in new LanguageManager().GetItems())
{
...
}
return View(model);
}
And ofc I have my model containing the data properties.
I can already display values bound inside my model in my view but I cannot seem to go the way back, meaning if the user checks the checkbox, how do I retrieve that is has been checked?
(Same would go for an editor or entry field)
How can I access the data from my checkbox?
EDIT:
I already have a form of which the checkbox is a child:
<form action="#Url.Action("SaveIndex")" method="POST" id="idForm">
#Html.HiddenFor(m => m.AutoCloseWindow)
#Html.HiddenFor(m => m.Item.Id)
#Html.CheckBoxFor(m => m.Test2)
But when I set a stoppoint at the corresponding function:
public ActionResult SaveIndex(Product item, List<GeneralLanguageEntry> languages, bool autoclosewindow = false)
{
...
return RedirectToAction("Index", new { autoclosewindow = autoclosewindow, refreshOpener = true, id = productFromDb.Id });
}
The model is not returned here... So i cannot see my altered checkbox
You need to use a rendered control from the html helper rather than just putting a checkbox on the page. This will bind the control to the property in your model.
#Html.CheckBoxFor(m => m.YourBoolValue)
Make sure you have a method that will accept your post data when the form is submitted:
[HttpPost]
public ActionResult SaveIndex(Product item)
...
Related
I need to disable button when property 'Flag' is true. This is my model and controller.
public class User {
public string Name { get; set; }
public bool Flag{ get; set; }
}
controller
public ViewResult Index() {
var userFlag = context.Users.Where(u => u.Flag = true).FirstOrDefault();
if (userFlag != false)
{
// disable button
}
else
{
// enable button
}
return View();
}
You disable the button in the view, not in the controller. First, the controller needs to send some information to the view. Ideally this is in the form of a view model, but for now let's just put a simple value into the ViewBag. Something like this:
ViewBag.UserFlag = userFlag;
return View();
Then in the view you can use that value. For example:
#if(ViewBag.UserFlag == true)
{
<button type="button" disabled>Click here</button>
}
else
{
<button type="button">Click here</button>
}
Or however your button is "enabled" vs. "disabled" in your HTML. You could even compress this into a single line using the ternary conditional operator if you want, it's a matter of personal preference.
But the point is that the controller simply provides the view with the data it needs to render the UI. It's then the view's responsibility to respond to that data and render the UI.
You have to pass that flag (boolean value) to the view and conditionally render the button with disabled attribute
You can pass the boolean value in multiple ways.
If you have a view model, set it's corresponding property. Let's say you have a view model called YourViewModel for your view and it has a IsEnabled property of boolean type ,set that in your action method and send the view model to the view.
So in your action method
var vm = new YourViewModel();
var user = context.Users.Where(u => u.Flag == true).FirstOrDefault();
vm.IsEnabled= user != null && user.Flag;
// Pointless because you are getting the one with True;
// So the value will be always true if user is not null
return View(vm);
and the view, check the IsEnabled property of your model,
#model YourViewModel
#if (Model.IsEnabled)
{
<input type="submit" value="Save" />
}
else
{
<input type="submit" value="Save" disabled="disabled" />
}
Or if you do not have a view model/your view is not strongly typed to any class, you can pass the boolean value as the model of the page
var user = context.Users.Where(u => u.Flag = true).FirstOrDefault();
var flag= user != null && user.Flag;
// Pointless because you are getting the one with True;
// So the value will be always true if user is not null
return View("Index",flag);
and in the view
#model bool
#if (Model)
{
<input type="submit" value="Save" />
}
else
{
<input type="submit" value="Save" disabled="disabled"/>
}
Another option is to use ViewBag to transfer this boolean flag from action method to view.
var user = context.Users.Where(u => u.Flag == true).FirstOrDefault();
ViewBag.IsEnabled = user != null && user.Flag;
// Pointless because you are getting the one with True;
// So the value will be always true if user is not null
return View();
and in the view
#if (ViewBag.IsEnabled !=null && ViewBag.IsEnabled)
{
<input type="submit" value="Save" />
}
else
{
<input type="submit" value="Save" disabled="disabled" />
}
Here i am rendering the enabled button only if the Flag value of your record is true. Adjust the code to negate it as needed ( in your question, it is the other way)
You cas use ViewBag to pass flag value from controller to view as
public ViewResult Index() {
var userFlag = context.Users.Where(u => u.Flag = true).FirstOrDefault();
ViewBag.UserFlag = userFlag == null ? true : false;
return View();
}
You can disable button in view as
<input type="button" value="Save" #{ if (ViewBag.UserFlag == true){ #: disabled="disabled"} } />
So here's my situation.
Let's say I have a view called TheView.cshtml. TheView.cshtml has a ViewModel called TheViewModel.cs. In TheViewModel.cs, resides a List of an object (TheObject) called TheObjectList.
I have an editor template for TheObject called TheObject.cshtml. Using this editor template, I can simply display all of the items in the TheObjectList with #Html.EditorFor(model => model.TheObjectList).
However, now I want to add objects to this list dynamically. I have an AJAX function, which calls a simple partial view to give the user a blank row to add a new "TheObject", however, any new TheObject I add dynamically is not considered part of the original TheObjectList.
This is because each item in the original TheObjectList is created with a certain prefix based on its index in the original list, whereas each new dynamic TheObject is created without a prefix, thus Razor does not see it as part of the list.
Is there a way around this?
TheView.cshtml
#model Models.ViewModels.TheViewModel
<table id="Table">
<tbody>
#Html.EditorFor(m => m.TheObjectList);
</tbody>
</table>
<button id="AddObject" type="button" class="btn btn-primary">Add Object</button>
TheViewModel.cs
public class TheViewModel
{
public List<TheObject> TheObjectList { get; set; }
}
AddObject Controller Method
public IActionResult AddObject()
{
return PartialView("_EmptyRow", new TheObject());
}
AJAX Method to Add Object
$('#AddObject').click(function () {
$.ajax({
url: 'AddObject',
cache: false,
success: function (data) {
$('#Table > tbody').append(data);
},
error: function (a, b, c) {
alert(a + " " + b + " " + c);
}
});
});
You basically needs to generate/return markup which looks same as what the editor template generates for your form fields except for the element index . You need to pass the index from client side which will be a part of the form field name.
Let's assume your editor template looks like below and your TheObject has a GroupName property
#model TheObject
<div>
#Html.HiddenFor(x => x.GroupName)
#Html.TextBoxFor(s=>s.GroupName,new {#class="thingRow"})
</div>
Now when you render your page with your current code, Editor template will generate input fields like this
<input class="thingRow" id="TheObjectList_0__GroupName"
name="TheObjectList[0].GroupName" type="text" value="Something">
where 0 will be replaced with the index of the items in your TheObjectList collection.
Now let's say you already have 5 items in the collection, So when user clicks add button, you want to generate markup like above except 0 will be replaced with 5(for the sixth item). So let's update the ajax call to include the current number of items.
$('#AddObject').click(function () {
var i = $(".thingRow").length;
$.ajax({
url: 'AddObject?index=' + i,
success: function (data) {
$('#Table > tbody').append(data);
},
error: function (a, b, c) {
console.log(a, b, c);
}
});
});
That means, we need to accept the index value in our action method. Since we need to pass this index value from action method to our view to build the input field name value, I added a property to your class called Index
public ActionResult AddObject(int index)
{
return PartialView("_EmptyRow", new TheObject { Index = index});
}
Now in your _EmptyRow partial view,
#model TheObject
<input id="TheObjectList_#(Model.Index)__GroupName"class="thingRow"
name="TheObjectList[#(Model.Index)].GroupName" type="text" value=""/>
Now when you submit the form, model binding will work for these dynamically added items, assuming you have your Table inside a form.
#model TheViewModel
#using (Html.BeginForm())
{
<table id="Table">
<tbody>
#Html.EditorFor(m => m.TheObjectList);
</tbody>
</table>
<button id="AddObject" type="button" class="btn btn-primary">Add Object</button>
<button type="submit" class="btn btn-primary">Save</button>
}
I have created a dropdownlist using html helper.
It's able to get the value and bind to dropdown.
How can i pass the selected dropdown value to controller?
My View:
#Html.DropDownList("Language", new SelectList(ViewBag.LangList, "Text", "Value"))
<input type="button" class="btn" title="Filter By Language"
value="Filter By Language" onclick="location.href='#Url.Action("SURV_Answer_Result", "SURV_Answer",
new { Survey_ID = Model[0].Survey_ID, Language = ViewBag.LangList })'" />
My Controller to get Language and bind into dropdown:
public ActionResult SURV_GetLanguage(int Survey_ID)
{
var getlanguagelist = from r in db.SURV_Question_Ext_Model
join s in db.SURV_Question_Model on r.Qext_Question_ID equals s.Question_ID
where s.Question_Survey_ID == Survey_ID
group new { r, s } by r.Qext_Language into grp
select grp.FirstOrDefault();
foreach (var item in getlanguagelist.ToList())
{
List<SelectListItem> langResult = new List<SelectListItem>();
foreach (var item2 in getlanguagelist)
{
SelectListItem temp = new SelectListItem();
temp.Text = item2.r.Qext_Language;
temp.Value = item2.r.Qext_Language;
langResult.Add(temp);
}
ViewBag.LangList = langResult;
}
return View(ViewBag.Langlist) ;
}
And i want pass the Language to the controller below:
public ActionResult SURV_Answer_Result(int Survey_ID, string Language)
{
List<AnswerQuestionViewModel> viewmodel = new List<AnswerQuestionViewModel>();
SURV_GetLanguage(Survey_ID);
// do whatever i want...
}
Your button in the view istype="button" and you have attached a onclick event which will just redirect to the SURV_Answer_Result passing the original ViewBag property back to the method (which will not bind to string Language because its List<SelectListItem>.
You need a form with FormMethod.Get
#using (Html.BeginForm("SURV_GetLanguage", "ControllerName", new { Survey_ID = Model[0].Survey_ID }, FormMethod.Get))
{
#Html.DropDownList("Language", (Enumerable<SelectListItem>)ViewBag.LangList)
<input type="submit" ... />
}
Notes:
The Survey_ID has been added to the form as a route value
ViewBag.LangList is Enumerable<SelectListItem> which is all that
is required by the DropDownList() helper so there is no point in
the extra overhead of creating another SelectList from it
(SelectList IS Enumerable<SelectListItem>)
The code you have used would work if you change the method signature on the controller to public ActionResult SURV_GetLanguage(int Survey_ID, string Language = null). You could then test for nulls and process as necessary.
However it would be better to wrap the dropdownlist inside a form, and use a POST request. Something like:
#using (Html.BeginForm("SURV_GetLanguage","ControllerName",FormMethod.Post))
{
#Html.DropDownList("Language", new SelectList(ViewBag.LangList, "Text", "Value"))
<input type="submit" class="btn" />
}
Then in the controller you could have a new method:
[HttpPost]
public ActionResult SURV_GetLanguage(string Language)
{
//Do whatever you want with language.
}
There are two ways,
1) You can put your dropdown and submit button into a form containing action parameter. On button press, your form will be submitted to its action. Your action must contain a parameter with name 'Languages'. It will give you selected value.
All the parameters of action, if matching to 'name' property of controls, will contain their values on form submit.
2) You can get selected value from dropdown by using jquery and then use either window.location or build url for form's action and call submit.
i want to change grid date when the user change drop down values with ajax.
this is my C# code:
public ActionResult Index(string name)
{
ViewBag.Drop = db.Students.Select(r => r.Fname);
var model = from r in db.Students
where r.Fname == name
select r;
return View(model);
}
and this is cshtml file:
#using (Ajax.BeginForm("Index", new AjaxOptions
{
UpdateTargetId = "grid",
HttpMethod = "GET"
}
))
{
#Html.DropDownList("name", new SelectList(ViewBag.Drop));
<input type = "submit" value = "submit" />
}
<div id= "grid">
</div>
my problem is that when i change drop down values all of views are shown again. i don't want to see new view , just want to change grid data. how can i do that?
Do you have an action method which returns only the Grid data ? if not, create one
public ActionResult GridData(string name)
{
var gridItems=repo.GetCustomers(name).ToList();
//the above method can be replaced by your
// actual method which returns the data for grid
return View(model);
}
I am simply assumuing you have a Customer model with properties called FirstName and LastName and you want to show a list of Customers in the Grid. You may replace those with your actual class names and properties.
Make sure you have a view called GridData.cshtml which will render the HTML markup for your Grid
#model IEnumerable<YourNameSpace.Customer>
#{
Layout=null;
}
<table>
#foreach(var item in Model)
{
<tr><td>item.FirstName</td><td>item.LastName</td></td>
}
I would write simple (and clean) code like below instead of using Ajax.BeginForm
#Html.DropDownList("name", new SelectList(ViewBag.Drop));
<div id= "grid"></grid>
<script type="text/javascript">
$(function(){
$("select[name='name']").change(function(){
var url="#Url.Action("GridData","YourControllerName")"+"?name="+$(this).val();
$("#grid").load(url);
});
});
</script>
I have a dropdownlist that is being populated by a sql server, I am using Visual Studio 2010, cshtml, with razor as well as using the MVC pattern to create this project. What I am trying to do is when someone selects a value from the dropdown list on change it will update the page with information about that book.
I need help with the three things below:
user selects a book from the dropdownlist how to get the Book Name back to the controller
The server (retrieve the information from the server about the book) and
Back to view to be displayed.
I started with getting the dropdown poplulated.
My View looks like this
BookName: #Html.DropDownList("BookName", ViewData["BookName"] as IEnumerable<SelectListItem>, new { id = "UserSelectedValue" })
My Controller:
public ActionResult Index()
{
ViewData["BookName"] = new SelectList(_context.BookName.Select(a => a.Book_Name).Distinct());
return View();
}
A dropdown list can't cause the page to post back to your controller on its own. You need to do one of two things:
Add a submit button so that the user changes the dropdown and then clicks a button to view the results.
Use javascript to submit the form on the element's change event.
Either way, you will need to wrap the dropdown/submit button in a form.
Option 1
<form>
BookName: #Html.DropDownList("BookName", ViewData["BookName"] as IEnumerable<SelectListItem>, new { id = "UserSelectedValue" })
<input type="submit" value="Show results" />
</form>
Option 2
<script type="text/javascript">
// assuming you're using jQuery
$(function() {
$('#UserSelectedValue').change(function() {
$(this).parent('form').submit();
});
});
</script>
<form>
BookName: #Html.DropDownList("BookName", ViewData["BookName"] as IEnumerable<SelectListItem>, new { id = "UserSelectedValue" })
<input type="submit" value="Show results" />
</form>
Your controller code would then become something like:
public ActionResult Index(string bookName)
{
ViewData["BookName"] = new SelectList(_context.BookName.Select(a => a.Book_Name).Distinct());
if (!string.IsNullOrWhiteSpace(bookName))
{
ViewData["Books"] = _context.BookName.Where(b => b.Book_Name == bookName).ToList();
}
return View();
}