Pass model Id to partialView in order to edit - asp.net-mvc

I have a list of Photography objects that I pass into a view:-
Public class Photography
{
public Photography()
{
Name = "";
Description = "";
Category = "";
ImgUrl = "";
IsAccordion = false;
}
public string Name { get; set; }
public string Description { get; set; }
public string Category { get; set; }
public string ImgUrl { get; set; }
public bool IsAccordion { get; set; }
}
In my view I loop through the list like this:
#foreach (var item in Model.Photographys)
{
<li class="span3" style="text-align: center">
<div class="thumbnail thumbnail-1">
<h3 style="margin-bottom: 10px;">#item.Name</h3>
<div class="">
<div class="">
<img src="#item.ImgUrl" alt="" style="visibility: visible; opacity: 1;">
</div>
</div>
<section>
<p>#item.Description</p>
Read More
<p>#item.IsAccordion</p>
</section>
</div>
</li>
}
What I want to do is to have a partial view that lets me edit the properties of photo i click. I have created a partial view using the scaffoldoption "Edit"..It looks like this:
#model aPhoto_web.Models.AdminPages.Photography
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Photography</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
}
etc etc...
Most partialViews I read about gets rendered directly when the parentview gets rendered..That is not what I want...I only want the partialView to appear when I somehow pass my Photo-object to it.
I know this is a "big" question but if anyone can point me in the right direction it´d be great! Thanks.
EDIT to clarify:
Have a look at this code where I have added an "RenderPartial" at the bottom of the loop.
#foreach (var item in Model.Photographys)
{
<li class="span3" style="text-align: center">
<div class="thumbnail thumbnail-1">
<h3 style="margin-bottom: 10px;">#item.Name</h3>
<div class="">
<div class="">
<img src="#item.ImgUrl" alt="" style="visibility: visible; opacity: 1;">
</div>
</div>
<section>
<p>#item.Description</p>
Read More
<p>#item.IsAccordion</p>
</section>
</div>
#{
Html.RenderPartial("_editPhoto", item);
}
</li>
}
This renders a partial-view for every item in the loop of course. I would like a method that passes the object I click to the partial...
EDIT:
public ActionResult EditPhoto(string id)
{
var photo = RavenSession.Load<ContentPage>(id) as Photography;
return PartialView("_editPhoto", photo);
}

First you have to add a controller method which takes Photography Name/ID (It's better if you can add ID property to Photography class) as argument and returns the Partial view you created.
Then when you click the photo you can use Jquery to pass the Photography Name/ID to created controller method and you can display the result using popup or within a particular element (e.g. DIV) inside your page.
EXAMPLE
When you loop Photography objects inside your view you can add a class and ID property to your img tag as follows;
<img src="#item.ImgUrl" alt="" class="photography-image" data-imgId="#item.ID" style="visibility: visible; opacity: 1;">
Then using jquery and jquery UI you can open a dialog box to display the partial view. Check the sample code below.
$( ".photography-image" ).click(function() {
e.preventDefault();
$("<div></div>")
.addClass("dialog")
.appendTo("body")
.dialog({
close: function () { $(this).remove() },
modal: true,
height: 500,
width: 500
})
.load("/controler/method?photographyId=" + $(this).data("imgId"));
});
Thanks!

Related

Data not binding to model from partial view when using TextBoxfor

In my project we have one partial view which is used to book details of a job. I have added new property WorkerID to model which is used in this partial view and main view. In the partial view using html.textboxfor i have added a field for workerid.
Model:
[Display(Name = "Worker Name")]
public Int32? WorkerID { get; set; }
[UIHint("CheckBoxNullable")]
[Display(Name = "Confirm Client")]
public bool ConfirmClient { get; set; }
[UIHint("CheckBoxNullable")]
[Display(Name = "Confirm Worker")]
public bool ConfirmWorker { get; set; }
[UIHint("CheckBoxNullable")]
[Display(Name = "Plan")]
public bool Plan { get; set; }
Partial View:
#model BookingsModel
<style>
div.k-edit-form-container {
width: auto;
}
</style>
<style>
.k-textbox {
width: 100% !important;
height: 34px !important;
}
.form-control {
padding: 0px 6px;
}
</style>
<div class="col-lg-11">
<ul class="errors alert alert-danger" style="display:none;"></ul>
<div class="form-group">
#Html.LabelFor(model => model.ShiftName)<span class="colon">:</span>
<label id="ShiftValue"></label>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StartDate)<span class="colon">:</span>
#Html.EditorFor(model => model.StartDate)
#Html.ValidationMessageFor(model => model.StartDate, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.EndDate)<span class="colon">:</span>
#Html.EditorFor(model => model.EndDate)
#Html.ValidationMessageFor(model => model.EndDate, "", new { #class = "text-danger" })
</div>
<div class="form-group" id="AllowQuickFill">
#Html.LabelFor(model => model.WorkerID)<span class="colon">:</span>
#Html.EditorFor(model => model.WorkerID, new { #class = "form-control", #placeholder = "Select Worker", #style = "Width:100%;" })
<label>Confirm Client</label><span class="colon">:</span> <input type="checkbox" id="chkConfirmClient" name="ConfirmClient" value="0" />
<label>Confirm Worker</label><span class="colon">:</span> <input type="checkbox" id="chkConfirmWorker" name="ConfirmWorker" value="0" />
<label>Plan</label><span class="colon">:</span> <input type="checkbox" id="chkPlan" name="Plan" value="0" />
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
initializeCombo("WorkerID", "/Workers/GetDataForCombo?workerStatusTypeID=3");
});
</script>
The InitializeCombo is a method we have created which loads drop down box. Out of 4 new properties which i added in the model only value of workerid is not getting passed to controller. When i run the application WorkerID drop down is get loaded properly, for testing i placed alerts to get value from drop down when user changes or selects any worker and it gave proper notification also.
If i change workerId from TextBoxFor to EditorFor then it works fine, but in that case it is not allowing me to define WorkerID property in model as nullable and this property should be defined as nullable. In my project i have used TextBoxFor in almost all places where i want to load comboboxes in this way and it works fine. But i am not able to find out why it is not working in this instance.
Regards,
Savan Parmar

How to use SweetAlert before return RedirectToAction by Form Post?

Model
public class Company{
[StringLength(30)]
public string Name{ get; set; }
[StringLength(15)]
public string RegisterNo { get; set; }
}
View
<form id="form" method="post" action="/Controller/Save" style="font-size:13px;">
<div class="row pb-3">
<div class="form-row">
<div class="col-md-3">
<div class="position-relative form-group">
<label class="">Company Name</label> #Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control", #maxlength = "30" } })
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6">
<div class="position-relative form-group">
<label class="">Reg No</label> #Html.EditorFor(model => model.RegisterNo, new { htmlAttributes = new { #class = "form-control", #maxlength = "15" } })
</div>
</div>
</div>
</div>
</form>
<button name="submit">Save</button>
Controller
public ActionResult Save(Company CompDet){
string Name = CompDet.Name;
string RegNo = CompDet.RegisterNo;
//then Connect DB and Save DB
//HOW TO use SweetAlert before, return RedirectToAction
}
I'm currently using, return RedirectToAction Only.
How to add SweetAlert before RedirectToAction?
Using Ajax Post or Form Post?
Possible that using Ajax & Form Post Together?
After Saving -> Show Sweetalert success -> return redirectToAction
I'm still at the learning level. Please Help.
Thank You

Pass object to partial view

I have this controller which fetches an object that I would like to render in a partial view:
public ActionResult EditPhoto(string id)
{
var photo = RavenSession.Load<ContentPage>(id);
return View("_editPhoto");
}
Its the photo I would like to pass to my partial view.
I have this in my view:
#{
Html.RenderPartial("_editPhoto" );
}
How will I go about to pass my photo into the partial view in order for it to render in its parent?
EDIT:
This is how I pass the object to the controller:
#foreach (var item in Model.Photographys)
{
<li class="span3" style="text-align: center">
<div class="thumbnail thumbnail-1">
#Html.ActionLink(item.Name,
"EditPhoto", // <-- ActionMethod
new { id = item.Id }, // <-- Route arguments.
null // <-- htmlArguments .. which are none. You need this value
// otherwise you call the WRONG method ...
// (refer to comments, below).
)
<h3 style="margin-bottom: 10px;">#item.Name</h3>
<div class="">
<div class="">
<img src="#item.ImgUrl" alt="" style="visibility: visible; opacity: 1;">
</div>
</div>
<section>
<p>#item.Description</p>
Read More
<p>#item.IsAccordion</p>
</section>
</div>
</li>
}
There seems a problem with this line however:
#{
Html.RenderPartial("_editPhoto" , Model);
}
Model gets underlined explaining that the Model passed into it (Photo) is not the right one..It seems that _editPhoto inherits the same Model as its parent maybe?
I managed to do this in the view:
#{
var i = new Photography();
Html.RenderPartial("_editPhoto", i);
}
The problem now is that the partialView gets rendered in a new window and not in its parent as I want it to.
UPDATE
Im gonna give this one last go, wont create a new question:
This is my controller passing a photo to a partial view:
public ActionResult EditPhoto(string id)
{
var photo = RavenSession.Load<ContentPage>(id) as Photography;
return PartialView("_editPhoto", photo);
}
My "mainview" contains this code to render the partial view with the photo getting sent to it:
<div class="form-control">
#{
var model = new Photography();
Html.Partial("_editPhoto",model);
}
</div>
This opens up a new window where my new photo shows up. I would like it to get rendered inside of its parents view the same way as it gets rendered automaticaly when i first visit the page...
Your controller action method should be:
public ActionResult EditPhoto(string id)
{
var photo = RavenSession.Load<ContentPage>(id);
return View("EditPhoto",photo);
}
and your "EditPhoto" view should be:
#{ Html.RenderPartial("_editPhoto",Model); }
Update
Your controller action method should be:
public ActionResult Photos()
{
return View();
}
public ActionResult EditPhoto(string id)
{
var photo = RavenSession.Load<ContentPage>(id);
return View(photo);
}
your "EditPhoto" should be view (not a partialview), on link click, "EditPhoto" action method is called and it returns the "EditPhoto" view
This questions seems related to one of your previous question.
Controller should be as follows;
public ActionResult EditPhoto(string id)
{
var photo = RavenSession.Load<ContentPage>(id);
return PartialView("_editPhoto", photo);
}
In your partial view _editPhoto, you can have the following code. I assume photo variable is a Photography object.
#model aPhoto_web.Models.AdminPages.Photography
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Photography</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
</div>
}
Thanks!

How to Apply a Customized Editor Template for View Model in MVC 4

I have what I think is a easy problem but for the life of me I cant figure it out. I have a form which imports many emails from a multi-line text box. From that import, I generate a report that tells the user the status of the imported emails and any errors. I can generate the report data fine, but cant seem to display the "Errors" field properly in the view. The problem appears to be, the editor template for the "Errors" field, is not being used. My question is, how do I get the view to use and render the editor template for the "Errors" field. I have tried using UIHint, but it doesn't work. Any help would be appreciated.
ViewModels.cs
//**************************Report View Models***************************************
public class ShowErrors
{
public string EmailAddress { get; set; }
public string ErrorDescription { get; set; }
}
public class ReportViewModel
{
public int TotalEmails { get; set; }
public int SuccessEmails { get; set; }
public int DuplicateEmails { get; set; }
public int InvalidEmails { get; set; }
[UIHint("ShowErrors")]
public virtual ICollection<ShowErrors> Errors { get; set; }
}
public static class ViewModelHelpers
{
//*************************ReportViewModel Helpers**************************************
public static ShowErrors ShowErrors_ViewModel_To_Domain(this ShowErrors item)
{
var showErrors = new ShowErrors
{
EmailAddress = item.EmailAddress,
ErrorDescription = item.ErrorDescription
};
return (showErrors);
}
}
Controller for the Report:(Dont think the problem is here, I can generate the data for the report, just cant display it properly.
public ActionResult Import_Report(EmailEditViewModel emailEditViewModel)
{
string emailAddress = null;
string[] emailArray = Request.Form["ImportEmails"].Split (new string[] { System.Environment.NewLine }, StringSplitOptions.None);
var entityModified = new EmailContact();
var reportViewModel = new ReportViewModel();
Regex regex = new Regex(#"^([\w\.\-]+)#([\w\-]+)((\.(\w){2,3})+)$"); //Regular Expression that checks email address is valid
List<ShowErrors> errorList = new List<ShowErrors>();
foreach (string item in emailArray)
{
ShowErrors errorItem = new ShowErrors();
emailAddress = item.Trim();
reportViewModel.TotalEmails += 1;
Match match = regex.Match(emailAddress); //Check email is in valid format
if (emailAddress == null || emailAddress == "")
{
reportViewModel.TotalEmails -= 1;
}
else if (!match.Success)
{
//Log this email as duplicate
reportViewModel.InvalidEmails += 1;
errorItem.EmailAddress = emailAddress;
errorItem.ErrorDescription = "Invalid Email";
errorList.Add(errorItem);
}
else if (_globalClasses.IsDuplicateEmail(emailAddress) > 0)
{
//Log this email as duplicate
reportViewModel.DuplicateEmails += 1;
errorItem.EmailAddress = emailAddress;
errorItem.ErrorDescription = "Duplicate Email";
errorList.Add(errorItem);
}
else
{
entityModified.EmailAddress = emailAddress;
entityModified.ActiveCampaigns = entityModified.Campaigns.Count(); //Calculates how many campaigns a contact is a member
try
{
db.EmailContacts.Add(_crypto.EncryptAndSanitizeEmailContacts(entityModified));
db.SaveChanges();
reportViewModel.SuccessEmails += 1;
AddOrUpdateEmailContacts(entityModified, emailEditViewModel.Campaigns); //Saves campaigns selected to this contact
db.SaveChanges();
//return RedirectToAction("Contact_List");
}
catch { }
}
}
reportViewModel.Errors = errorList;
return View(reportViewModel);
}
Here is the View:
#model HoltsCA.ViewModels.ReportViewModel
#{
ViewBag.Title = "Import_Report";
Layout = "~/Views/Shared/_LayoutDashboard.cshtml";
}
<fieldset>
<legend></legend>
<div class="row col-md-6">
<div id="bootstrapTableHeader" class="row">
<div class="col-sm-12">
<h2 style="text-align:center; color:#fff; font-size:1.3em;">Import Contacts Report</h2>
</div>
</div>
<div id="bootstrapTableRow" class="row">
<div class="col-sm-7" style="text-align:right">Total Emails:</div>
<div class="col-sm-5" style="text-align:left">#Html.DisplayFor(model => model.TotalEmails)</div>
</div>
<div id="bootstrapTableRow" class="row">
<div class="col-sm-7" style="text-align:right">Success Imported Emails:</div>
<div class="col-sm-5" style="text-align:left">#Html.DisplayFor(model => model.SuccessEmails)</div>
</div>
<div id="bootstrapTableRow" class="row">
<div class="col-sm-7" style="text-align:right">Duplicate Emails:</div>
<div class="col-sm-5" style="text-align:left">#Html.DisplayFor(model => model.DuplicateEmails)</div>
</div>
<div id="bootstrapTableRow" class="row">
<div class="col-sm-7" style="text-align:right">Invalid Emails:</div>
<div class="col-sm-5" style="text-align:left">#Html.DisplayFor(model => model.InvalidEmails)</div>
</div>
<div class="row" style="height:50px"></div>
<div id="bootstrapTableHeader" class="row">
<div class="col-sm-12">
<h2 style="text-align:center; color:#fff; font-size:1.3em;">Error Report</h2>
</div>
</div>
<div id="bootstrapAccentRow" class="row">
<div class="col-sm-6" style="text-align:left">
<b>Email Address</b>
</div>
<div class="col-sm-6" style="text-align:left">
<b>Error Description</b>
</div>
</div>
<div id="bootstrapRow" class="row">
#Html.DisplayFor(model => model.Errors)
</div>
</div>
</fieldset>
<p>
#Html.ActionLink("Edit", "Edit", new { /* id=Model.PrimaryKey */ }) |
#Html.ActionLink("Back to List", "Index")
</p>
Finally Here is the Editor Template ShowErrors.cshtml
#model ShowErrors
#using HoltsCA.ViewModels
<fieldset>
<div class="col-md-6" style="text-align:left;">
#Html.DisplayFor(model => model.EmailAddress)
</div>
<div class="col-md-6" style="text-align:left;">
#Html.DisplayFor(model => model.ErrorDescription)
</div>
</fieldset>
I think you are trying to display errors by using editor template. Put your error template inside DisplayTemplates folder under Shared folder.
If you are using #Html.DisplayFor then your template should be in the DisplayTemplates folder and similar logic while displaying editing template. To specify which template to use you can also do
#Html.DisplayFor(model => model.Errors, "ShowErrors")
Another thing is your model.Errors is a List<ShowErrors> and inside your display template you have just #model ShowErrors instead you should display it like IEnumerable<ShowErrors> and iterate in the template to show all the errors.
#model IEnumerable<ShowErrors>
#using HoltsCA.ViewModels
#foreach(var error in Model)
{
<div class="col-md-6" style="text-align:left;">
#Html.DisplayFor(error => error.EmailAddress)
</div>
<div class="col-md-6" style="text-align:left;">
#Html.DisplayFor(error => error.ErrorDescription)
</div>
}
That's not an EditorTemplate, it's a DisplayTemplate.
You just need to create a folder named "DisplayTemplates" under Views/Shared, and put the ShowErrors.cshtml partial view in the folder.
Your model is a List<ShowErrors> not a ShowError object.
You could change your view to this:
#model List<ShowErrors>
#using HoltsCA.ViewModels
#foreach(var error in Model)
{
<fieldset>
<div class="col-md-6" style="text-align:left;">
#Html.DisplayFor(error => error .EmailAddress)
</div>
<div class="col-md-6" style="text-align:left;">
#Html.DisplayFor(error => error .ErrorDescription)
</div>
</fieldset>

After submit a form in a Area not displayed none of validation message?

I have a area and at this area i have a PostController, and a action with Add name for GET method and a action with Add name for POST method,after submit form i add error to modelstate BUT after postback,not displayed none of validation message and staus code is:301 Moved Permanently !!!
my viewmodel:
public class NewPostViewModel
{
[Required(ErrorMessage = "Please enter title.")]
public string Title { get; set; }
[AllowHtml]
[Required(ErrorMessage = "Please enter article content.")]
public string Content { get; set; }
[Required(ErrorMessage = "Please enter a tag.")]
public string Tags { get; set; }
public bool PublishNow { get; set; }
public string PublishDate { get; set; }
public string PublishTime { get; set; }
}
my view:
#model Soleimanzadeh.Models.ViewModels.NewPostViewModel
#{
ViewBag.Title = "Add";
Layout = MVC.Admin.Shared.Views.BaseLayout;
}
#using (Html.BeginForm(MVC.Admin.Post.Add(), FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(false, null, new { #class = "alert" })
<div class="row-fluid">
<div class="span9">
<div class="row-fluid">
<div class="span8">
#Html.TextBoxFor(np => np.Title, new { #class = "span12", placeholder = "Title" })
#Html.ValidationMessageFor(model=>model.Title)
</div>
</div>
<div class="row-fluid">
<div class="span12">
#Html.TextAreaFor(np => np.Content)
#Html.ValidationMessageFor(model=>model.Content)
</div>
</div>
</div>
<div class="span3">
<div class="row-fluid">
<div class="post-options-container">
<div class="header">
Tags
</div>
<div class="content">
<input type="text" placeholder="tags" class="tagManager" style="width: 100px;" />
</div>
</div>
</div>
<div class="row-fluid">
<div class="post-options-container">
<div class="header">
Status
</div>
<div class="content">
<label class="checkbox">
#Html.CheckBoxFor(np => np.PublishNow)
Publish Now?
</label>
<div>
Publish Date:
#Html.TextBoxFor(np => np.PublishDate, new { #class = "calcInput" })
</div>
<div>
Publish Time:
#Html.TextBoxFor(np => np.PublishTime, new { #class = "timeInput" })
</div>
<div>
<input type="submit" value="Save"/>
</div>
</div>
</div>
</div>
</div>
</div>
}
#*some scripts here*#
my controller:
public partial class PostController : Controller
{
public virtual ActionResult Add()
{
var newPost = new NewPostViewModel();
return View(MVC.Admin.Post.Views.Add, newPost);
}
[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult Add(NewPostViewModel post)
{
ModelState.AddModelError("Content","Wrong");
return this.View(MVC.Admin.Post.Views.Add, post);
}
}
Also i use redactor html editor for Content.
Solution:
i use http://lowercaseroutesmvc.codeplex.com/ for convert urls to lowercase,but i not enabled this tool in area section and page redirectd after submit form.

Resources