save position from all draggable divs on save mvc - asp.net-mvc

I want to make a table arrangement system for a restaurant admin page.
I want a table index page which shows all tables as divs inside a bigger div(map of the restaurant).
The restaurant van add tables and these tables be added to that index page.
The tables can be dragged with the jquery draggable function.
This page needs to have a save button and if clicked it needs to store all the tables positions to the database.
My model is like this:
public class table
{
public int id { get; set; }
public string tableName { get; set; }
public bool available { get; set; }
public float positionY { get; set; }
public float positionX { get; set; }
}
My Controller which does not have much now.
private BonTempsDbContext db = new BonTempsDbContext();
// GET: tafel
public ActionResult Index()
{
return View(db.Tafel.ToList());
}
// GET: Menu/Create
public ActionResult Create()
{
return View();
}
// POST: Menu/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,tafelNaam,beschikbaar,positionY,positionX")] Tafel tafel)
{
if (ModelState.IsValid)
{
db.Tafel.Add(tafel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(tafel);
}
and my view looks like this:
#model IEnumerable<BonTempsMVC.Table>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<div class="VoegToeBtn">
<a href="/table/create">
<span class="btn btn-default">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Create new table
</span>
</a>
</div>
<div id="tablewrapper">
#foreach (var item in Model)
{
<div class="draggable ui-widget-content" id="#Html.DisplayFor(ModelItem => item.id)">
<p>#Html.DisplayFor(ModelItem => item.tablename)</p>
</div>
}
</div>
<script>
$(".draggable").draggable({
snap: ".draggable",
snapMode: "outer"
});
</script>
now there needs to be a button which executes a query that update all the table records with the right positions or only the tables which moved if that is possible.

You can create an input tag on your view page. You can specify the Action method which will be invoked when the button is clicked by specifying the onclick attribute. Also, you can pass parameters so that the method will receive the coordinates:
#using (Html.BeginForm("ActionMethodName","ControllerName",new {param1 = coordinate1, param2 = coordinate2}))
{
... your input, labels, textboxes and other html controls go here
<input class="button" id="Update" type="submit" value="Submit" />
}
Then inside your controller, you can write an Action method which will have 2 parameters; viz; param1 and param2 which will do the task of updating the table parameters by writing a linq query:
public ActionResult ActionMethodName(int param1,int param2)
{
//LINQ query goes here for updating table coordinates
}

Related

SelectediAlertIndex from SelectTagHelper (apparently) not passed to Index.cshtml from LoadAlert(…) …RedirectToAction(“Index”,”Alerts”)

Struggling with getting the SelectedAlertIndex (int) from AspNetCore MVC view page:
#{
<h4>#Model.Alerts.Count Alerts</h4>
<form asp-controller="Alerts" asp-action="LoadAlert" method="post">
<select asp-for="SelectedAlertIndex" asp-items="#Model.Alert_Identifiers">
<option>Select one</option>
</select>
<br />
<input type="submit" name="LoadAlert" value="LoadAlert" />
</form>
}
thru AlertsController.cs:
[HttpPost]
public IActionResult LoadAlert(Alert obj, string LoadAlert)
{
if (!string.IsNullOrEmpty(LoadAlert))
{
ViewBag.Message = "Alert loaded successfully";
}
return RedirectToAction("Index", "Alerts")
}
to #foreach loop inside table in Views/Alerts/Index.cshtml:
#model IEnumerable<edxl_cap_v1_2.Models.ContentViewModels.Alert>
…
<table id="elementTable" class="smallText">
#foreach (var item in Model)
{
#*#while(item.AlertIndex == item.SelectedAlertIndex)
{*#
<tr>
Without the nested #while loop, the table of rows, one for each data element, displays all three records of 13 data elements each, but what I want is to display the set of 13 data elements for the one selected record using the int value of the AlertIndex selected from the Select Tag Helper dropdownlist. If I uncomment the #while loop only the border of the “elementTable” is displayed with no rows. This also happens when I try adding a “Where” clause to the #foreach loop:
#foreach (var item in Model.Where(item => item.AlertIndex == item.SelectedAlertIndex))
{
I’m trying to only show relevant code for the problem, but just in case it’s needed here’s the basic model:
public class AlertViewModel
{
public int SelectedAlertIndex { get; set; }
public List<SelectListItem> Alert_Identifiers { get; set; }
public List<AlertVm> Alerts { get; set; }
}
public class AlertVm
{
[Key]
public int AlertIndex { get; set; }
[MaxLength(150)]
public string Alert_Identifier { get; set; }
}
I decided it probably wasn’t needed to show the Alert class of 13 elements that I ended up adding to the view model, from the original Alert.cs class.
I needed to change value of asp-action in the form tag helper usage to Index:
#{
<h4>#Model.Alerts.Count Alerts</h4>
<form asp-controller="Alerts" asp-action="Index" method="post">
<select asp-for="SelectedAlertIndex" asp-items="#Model.Alert_Identifiers">
<option>Select one</option>
</select>
<br />
<input type="submit" name="Index" value="LoadAlert" />
</form>
}
Then I needed to make sure that SelectedAlertIndex was spelled the same in all instances; changed its type to Nullable int (int?); put a null check in the HttpPost Index() action; and add a Where condition:
[HttpPost]
public IActionResult Index(Alert obj, int? SelectedAlertIndex)
{
if (SelectedAlertIndex.HasValue)
{
ViewBag.Message = "Alert loaded successfully";
}
return View(_context.Alert.Where(x => x.AlertIndex == SelectedAlertIndex));
}
Many Thanks to #Shyju

asp.net mvc displaying dropdown value

I have created a dropdownlist by fetching data from database.I want to display the selected value on click of submit. In controller I am trying to store the selected value in ViewBag and display it. When I debugged the code, I came to know that viewbag stores null value.The following line stores the value in viewbag.
ViewBag.scode = emp.Service_Code;
While debugging, Service_Code shows the value but it gets stored as null in ViewBag. Please help me in solving this issue.
Model
public class Employee
{
public int Service_Code { get; set; }
public string Service_Name { get; set; }
public IEnumerable<SelectListItem> ser_code { get; set; }
}
View
#model mvclearn.Models.Employee
#{
ViewBag.Title = "menu";
}
<link href="~/Content/bootstrap.css" rel="stylesheet" />
<div class="container">
#using (Html.BeginForm("save", "Test", FormMethod.Post))
{
#Html.DropDownListFor(m => m.Service_Code, Model.ser_code, "--select-",new { #class = "form-control" })
<input type="submit" value="submit" class="btn-block" />
}
</div>
<div>You entered:#ViewBag.scode</div>
Controller
public ActionResult menu()
{
RevenueDashboardEntities rdb = new RevenueDashboardEntities();
var model = new Employee()
{
ser_code = new SelectList(db.Services, "Service_Code", "Service_Name")
};
return View(model);
}
[HttpPost]
public ActionResult save(Employee emp)
{
RevenueDashboardEntities rdb = new RevenueDashboardEntities();
ViewBag.scode = emp.Service_Code;
return View("menu");
}
The selected value is already getting post in the action via model in Service_Code property of it.
What you need here is return your model back to view and it will populate the selected value with what was selected at form post:
[HttpPost]
public ActionResult save(Employee emp)
{
RevenueDashboardEntities rdb = new RevenueDashboardEntities();
// this is needed to populate the items of dropdown list again
emp.ser_code = new SelectList(db.Services, "Service_Code", "Service_Name");
// sending model back to view
return View("menu",emp);
}
Now the value will be auto selected on page load after form is posted and you can display the value on the page inside div by writing:
<div>You entered: #Model.Service_Code</div>

MVC BeginCollectionItem

I'm having some issue getting my partial view BeginCollectionItem to save to the database. I have a form which has a dynamic number of "sections" that can be added to the page, and within each of these fields there is a text box where the user can enter the section name.
As far as I can tell the BeginCollectionItem within the partial view is working properly, however I cannot post the info to the database. In my other forms I have used a [bind()] to send the data to the database, is it possible to get this into a list and then post that via a bind?
I've included my code below:
The Model:
namespace project.Models.SetupViewModels
{
public class SOPTopTemplateBuilderViewModel
{
public List<Section> Section { get; set; }
}
public class Section {
public int SectionId { get; set; }
public string SectionText { get; set; }
public string TopTempId { get; set; }
}
}
cshtml:
#model IEnumerable<project.Models.SetupViewModels.Section>
#using (Html.BeginForm("SOPTopTemplateBuilder", "Setup", FormMethod.Post))
{
<div class="main-holder" id="theform">
#foreach(var item in Model)
{
#Html.Partial("_SectionCreator", item)
}
</div>
<button id="add" type="button">Add</button>
<div class="form-group submit-row">
<div class="col-12 float-to-right">
<input type="submit" class="btn btn-default" value="continue" />
</div>
</div>
}
#section Scripts {
<script>
$(document).ready(function () {
var url = '#Url.Action("AddSection")';
var form = $('form');
var recipients = $('#theform');
$('#add').click(function() {
$.post(url, function(response) {
recipients.append(response);
// Reparse the validator for client side validation
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
});
});
</script>
}
Partial View:
#model project.Models.SetupViewModels.Section
#using HtmlHelpers.BeginCollectionItemCore
#using (Html.BeginCollectionItem("Section"))
{
<div class="new-section">
<div>
<p>New Section</p>
#Html.HiddenFor(m => m.SectionId, new { #class="id" })
#Html.EditorFor(m => m.SectionText, new { #class = "form-control limit-form"})
</div>
</div>
}
Controller:
[HttpPost]
public PartialViewResult AddSection()
{
return PartialView("_SectionCreator", new Section());
}
[HttpGet]
public ActionResult SOPTopTemplateBuilder(){
List<Section> model = new List<Section>();
return View(model);
}
[HttpPost]
public ActionResult SOPTopTemplateBuilder(IEnumerable<Section> soptop)
{
if (ModelState.IsValid)
{}
return View(soptop);
}
Your use of Html.BeginCollectionItem("Section") perpends Section[xxxx] to the name attribute (where xxxx is a Guid) so that you generating inputs with
<input name="Section[xxxx].SectionId" .... />
which posts back to a model containing a collection property named Sections.
Since you already have a model with that property, you can change the POST method to
[HttpPost]
public ActionResult SOPTopTemplateBuilder(SOPTopTemplateBuilderViewModel soptop)
other options include
Using your existing POST method and omitting the "Section" prefix
using Html.BeginCollectionItem("") which will generate
name="[xxxx].SectionId"
Changing the POST method signature to public ActionResult
SOPTopTemplateBuilder(IEnumerable<Section> section) (where the
name of the parameter matches the name of the prefix)
Using a BindAttribute to 'strip' the prefix from the form values
public ActionResult SOPTopTemplateBuilder([Bind(Prefix = "Section")]IEnumerable<Section> soptop)
As a side note, your editing data, so you should always use a view model (say public class SectionViewModel) rather than using data models in your view. - What is ViewModel in MVC?

Retrieving values from partial view during post method

I have a view which contains a dropdown list and on dropdownlist item being selected I load a partial view. And when the form is submitted I want to be able to get both the values from main view and partial view during form submit.
Here is the main view
#model AdminPortal.Areas.Hardware.Models.CreateModule
#{
ViewBag.Title = "Create Module";
Layout = "~/Views/shared/_BootstrapLayout.basic.cshtml";
}
#Html.ValidationSummary(true)
<fieldset class="form-horizontal">
<legend>Add a Module <small>Create</small></legend>
#using (Html.BeginForm("CreateModule", "Module", new{id="AddModuleForm"}))
{
#Html.ValidationSummary(true)
<div class ="controls">
<div class="input-block-level">#Html.TextBoxFor(model => model.ModuleId, new {#placeholder = "ModuleID"})</div>
<br/>
<div class ="input-block-level" id="selectedModuleTypeName">#Html.DropDownListFor(model => model.SelectedModuleTypeName, Model.TypeNames,"Select Moduletype", new{id = "ModuleList"})</div>
<br/>
<div id="partialDiv"></div>
</div>
<div class="form-actions" id="buttons">
<button type="submit" class="btn btn-primary" id="Submit">Save changes</button>
#Html.ActionLink("Cancel", "ModuleList", null, new { #class = "btn " })
</div>
}
</fieldset>
<div>
#Html.ActionLink("Back to List", "ModuleList")
</div>
<script>
$("#buttons").hide();
$("#ModuleList").on("change", function() {
var modId = $(this).val();
$.get('#Url.Action("GetModulePropertyName", "Module")', { moduleTypeValue: modId }, function(result) {
$("#partialDiv").html(result);
});
//uncomment following section to check if the partial view is working properly
/*.done(function() { alert("done"); })
.fail(function() { alert("fail"); })
.always(function() { alert("completed"); });*/
});
$("#buttons").show();
</script>
and here is the partial view
#model IEnumerable<string>
#foreach(var names in Model)
{
<div class="input-block-level">#Html.TextBoxFor(m=>names, new{Value="", placeholder=names})</div>
<br/>
}
Here is my model
public class CreateModule
{
//Empty form to handle form serialization
public CreateModule()
{
}
[Required]
public string ModuleId { get; set; }
[DataType(DataType.DateTime)]
public DateTime DateEntered { get; set; }
[Required]
public string SelectedModuleTypeName { get; set; }
public IEnumerable<SelectListItem> TypeNames { get; set; }
public List<Property> Properties { get; set; }
}
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
Here is the method that script in main view forwards to
[HttpGet]
public ActionResult GetModulePropertyName(string moduleTypeValue)
{
var moduleKindId = _repository.GetModuleKindId(moduleTypeValue);
var modulePropertyNames = _repository.GetModuleKindPropertyNames(moduleTypeValue);
return PartialView("GetModulePropertyName",modulePropertyNames);
}
and finally here is httppost method for the main view
[HttpPost]
public ActionResult CreateModule(CreateModule moduleV)
{
var module = new Module
{
ModuleTypeId = Convert.ToInt64(moduleV.SelectedModuleTypeName),
ModuleId = moduleV.ModuleId,
DateEntered = moduleV.DateEntered,
};
if (ModelState.IsValid)
{
_repository.AddModule(module);
Success("Module added successfully!");
return RedirectToAction("ModuleList", "Module", new {area = "Hardware"});
}
Error("Something went wrong!");
return RedirectToAction("CreateModule", "Module", new { area = "Hardware" });
}
Current situation:
When the form is posted, the properties value of the model that is being passed via partial view is null. I get other values, like typename, Module ID.
What I'd want:
I also want to get the value of properties that is being passed via partial view.
You don't have any input field for the Properties property anywhere in your form. So it will always be null. That's normal.
Here's how you could proceed. Start by setting the correct navigational property so that the helper generates correct names of the corresponding input fields.
Also make sure that you are passing an IEnumerable<Property> model to the partial if you want to be able to get them back correctly:
[HttpGet]
public ActionResult GetModulePropertyName(string moduleTypeValue)
{
var moduleKindId = _repository.GetModuleKindId(moduleTypeValue);
IList<Property> model = ...
return PartialView("GetModulePropertyName", model.ToList());
}
and in your partial view use an editor template:
#model IList<Property>
#{
// This indicates the current navigational context to the helpers
ViewData.TemplateInfo.HtmlFieldPrefix = "Properties";
}
#Html.EditorForModel()
and the last step is to define a custom editor template for the Property class: ~/Views/Shared/EditorTemplates/Property.cshtml (note that the name and location of the template is important)
#model Property
<div class="input-block-level">
#Html.HiddenFor(m => m.Name)
#Html.TextBoxFor(m => m.Value, new { placeholder = Model.Name })
</div>
<br />
Try using the
List<Property>
as a model in your partial view and pass the CreateModule.Properties as model from your View
The problem is model binder can not figure out there
#Html.TextBoxFor(m=>names, new{Value="", placeholder=names})
belongs to as the "names" is not a property on your model class. If you need to bind to the CreateModule.Properties you need to change the partial view to emit textboxes with aproprate names, like this one:
#model IEnumerable<string>
#
{
int i=0;
}
#foreach(var names in Model)
{
<div class="input-block-level">#Html.TextBox("Properties[" + i + "].Value")</div>
<br/>
}

how to add some own forms in a ASP.NET MVC create view?

i have a problem, i had created a controller and a view for adding a new item from a specific model. the view looks like:
#modelModels.UserItem
#{
ViewBag.Title = "New";
}
<h2>New</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Device</legend>
<div class="editor-label">
#Html.LabelFor(model => model.name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.name)
#Html.ValidationMessageFor(model => model.name)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
and the controller:
[HttpPost]
public ActionResult New(UserItem useritem)
{
if (ModelState.IsValid)
{
db.UserItems.AddObject(useritem);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(useritems);
}
how i want to add a dropdown to the form in the view like this:
<select id="Select1">
<option>MARS</option>
</select>
how to access the data from the form after it was submitted in the controller?
Have view model for your page,this view model will be used in your view. So, only include fields from your model that you really need. In Get action you should create this view model and get the needed properties from your model and map them to your view model.
public class UserItemViewModel
{
/* Properties you want from your model */
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
/* Property to keep selected item */
public string SelectedItem { get; set; }
/* Set of items to fill dropdown */
public IEnumerable<SelectListItem> SelectOptions { get; set; }
/* Fill the SelectListHere. This will be called from index controller */
public void FillOptions()
{
var items = new[] { "Mars", "Venus" }.
Select(x => new SelectListItem { Value = x, Text = x });
SelectOptions= new SelectList(items, "Value", "Text");
}
}
Change controller for receiving ViewModel instead of Model itself.
[HttpPost]
public ActionResult New(UserItemViewModel useritem)
{
/* Repopulate the dropdown, since the values are not posted with model. */
userItem.FillOptions();
if (ModelState.IsValid)
{
/* Create your actual model and add it to db */
// TODO: Map your properties from model to view model.
// Let's say you created a model with name userItemModel
db.UserItems.AddObject(userItemModel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(useritem);
}
You might need to change Index view controller little.(to fill dropdown)
[HttpGet]
public ActionResult Index()
{
/* Create new viewmodel fill the dropdown and pass it to view */
var viewModel = new UserItemViewModel();
viewModel.FillOptitons();
//TODO : From your model fill the required properties in view model as I mention.
return View(viewModel);
}
And your view,
/* Strongly typed view with viewmodel instead of model itself */
#modelModels.UserItemViewModel
/* This is the dropdown */
#Html.DropDownListFor(m => m.SelectedItem, Model.SelectOptions)
Add that property to your model
Use builtin EditorFor(preffered) or hand-written html to generate client-side input for that property.
Access submitted value by inspecting that property when user submits the form
I like emre's proposition of having a viewModel and I think is the Best solution to your question however just in case you don't want to go that way (you must have a really good reason because it is best) and still want a way to access the values of a form directly you can always use:
var x = Request["myFiledName"];
inside your controller to get to the values passed by your form.

Resources