I am working on a computer support incident management system.
Currently, a Review view for an incident contains several incident manipulation buttons, that are "rendered" onto the view with the help of the following logic:
A model for the view contains several methods that can tell if some action is allowed to be currently executed on this incident
A part ViewModel to which the Review view is bound:
...
public bool CanContactUser()
{
return _manager.CanContactUser(Incident, User);
}
public bool CanComment()
{
return _manager.CanSetComment(Incident);
}
...
In the view, depending on the result of these methods, the actual button for particular action is either displayed or not:
...
#if (Model.CanContactUser())
{
#Html.MakePopupForm("ContactUser", new[] { "id" }, title: "Register user contact", refreshOnSuccess: true, okText: "Save", cancelText: "Cancel", resizable: false)
}
#if (Model.CanComment())
{
#Html.MakePopupForm("Comment", new[] { "id" }, title: "Comment", refreshOnSuccess: true, okText: "Save", cancelText: "Cancel", resizable: false)
}
...
I feel that it is a bad practice. Even though it works, I am willing to have a collection of available buttons in memory (in C# code), I guess in a ViewModel class instance, and bind the view to render this collection.
How can this be achieved? Binding the view to a collection of buttons in particular. I can generate an abstract collection of List<AvailableButton> buttonsToRenderAsHtml ...But how do I link Razor to display it in a controlled fashion?
I think this depends on your preference.
If you have a contiguous set of buttons in your layout then you could add your property to your existing view model and then render in a loop. EG:
#foreach(var button in Model.AvailableButtons) {
YourButtonRenderMethod(button)
}
or have a shared partial view that can render a set of buttons with:
#model IEnumerable<AvailableButton>.
In that case you can just call:
#Html.RenderPartial("SetOfButtons", Model.AvailableButtons)
This is how I tend to build out my UI using composable partial views
But if your buttons are scattered in different areas of your view layout then I don't think you have a choice but to check individually.
It is strictly view logic, so you shouldn't feel bad about that in my opinion.
Related
i am learning mvc. so like to know what is the difference between view & partial view in mvc in terms of functionality.
normal view & partial view both render html in page....so what is the difference and limitation for two?
what are things are accomplish by partial view. please give me few scenario where people need to use partial view.
here is posting two code to load view based on dropdown value change.
$(function() {
$('#myddl').change(function() {
var url = $(this).data('url');
var value = $(this).val();
$('#result').load(url, { value: value })
});
});
public ActionResult Foo(string value)
{
SomeModel model = ...
return PartialView(model);
}
public ActionResult GetView(int id)
{
switch (id)
{
case 1:
return View("View1", model1);
break;
case 2:
return View("View2", model2);
break;
default:
return View("Default", modelDefault);
}
}
now see one action result return PartialView and another return just view to ajax method. which approach is right? when second approach need to use?
please guide me with knowledge. thanks
We use partial view to render a specific section of a page, like take an example of Customer. Your Index view of Customer controller will be a normal view while your grid of customers will be a partial view so that when you update or insert a new customer or delete a customer you will just render your partial view which contains grid of customers not the whole index view.
As far as i know, a partial is used as part of a view and can be shared across multiple views to provide extra functionality for those views. Also, views can be broken down to partials to make editing easier and eliminate redundancy. Hope it helps a little
Partial view kept to use as partial page of the main page(parent page).
What does mean of partial view? Actually in the main page we will have all the HTML page attributes as below:
html lang="en"
head
title
meta
body
But in partial view we will not have all above attributes.
Find the features of partial page:
1. Partial page will be light wait and get fitted into the any view.
2. This will use as the reusable component.
3. Partial view will be render inside of a View(parent view or page).
For all who coming from ASP.Net background they can understand partial view as user control.
Thanks
Afazal
mdafazal#gmail.com
I've got a Knockout viewmodel populated from a variety of Mvc actions.
A Category is chosen from the first dropdown (say Fruit, Meat, Drinks etc).
A second dropdown is automatically populated from the first choice. However, there may be 2 matches for fruit (say Apples, Oranges), 2 for meat (say Beef, Lamb) and many choices for drink (several hundred).
My page currently displays a search box depending on the Category chosen.
I was wondering how to automatically bind the second dropdown for Fruit & Meat, or wait and do the bind from the results of the search query.
Sorry this is vague - twitchy client! Very new to KnockoutJs.
Thanks in advance.
If I understood you right, you could create a method in your viewmodel which you bind to the change event of the dropdown.
Example method:
var myViewModel = {
firstDropDownArray: ko.observableArray([]),
secondDropDownArray: ko.observableArray([]),
// Validates Selection
validateSelection: function (item) {
var anotherList;
switch (item.toUpperCase()) {
case "FRUIT":
// Do something...
break;
case "DRINKS":
// Do something else...
break;
default:
}
}
};
Your Dropdown can bind then to the method like this:
<select id="FirstDropDown" data-bind="options: myViewModel.firstDropDownArray, <any other binding options>, event: {change: myViewModel.validateSelection(currentItem)}">
</select>
As stated here: event-binding,
When calling your handler, Knockout will supply the current model
value as the first parameter.
I'm assuming this means the currentItem will be the selected item when you are calling the method.
I know in my sample code I wrote item.toUpperCase() but that is just assuming the item is passed as a string. This syntax obviously has to change depending on how you have declared and populated your dropdown but in essence you still should be able to write a method in your viewmodel you can bind then to the change event,..or any other event you like.
At work I have been tasked with adding additional functionality to an existing MVC 3/Razor project. I haven't used MVC before, but am quite versed with Web Forms.
However, I am not quite sure where to place everything I need.
When the app is first loaded, a login page appears. When the user logs in successfully, the user sees a dashboard type page.
The new functionality is to detect whether the user has FollowUpItems with a Due Date < Now. If Count > 0 then display a Modal popup with some text and a link to 'View Followup Items'.
There is already a controller and action made for viewing Followup items. I need to display the modal, and I would like to make the modal a reuseable type of object - I am assuming/thinking a PartialView where I can pass in the name of the Controller, Action, Params for a possible ActionLink that I would display in the modal popup, and the message text, etc.
I need a little guidance on how to open the modal since it isn't attached to a click, but rather to whether an expression evaluates true or false, and where the best place for the pieces are.
Thanks in advance for the guidance
I would detect if the user has FollowUpItems in the Action that loads the dashboard page, and store that information in the ViewBag. For example,
public ActionResult Dashboard()
{
ViewBag.HasFollowupItems = UserHasFollowupItems();
return View();
}
In this example, UserHasFollowupItems() returns a string, something like 'true' or false'.
In the dashboard view, add an empty div into which the modal data will be loaded
<div id="followup_items"></div>
then add a document.ready() in the same view which defines the modal and determines if the modal should be loaded:
$(document).ready(function ()
{
// define modal
$("#followup_items").dialog({
autoOpen: false,
height: 'auto',
width: 825,
title: 'Followup Items',
position: [75, 75],
modal: true,
draggable: true,
closeOnEscape: true,
buttons: {
'Close': function ()
{
$(this).dialog('close');
}
},
close: function ()
{
$('.ui-widget-content').removeClass('ui-state-error');
},
});
if(#ViewBag.HasFollowupItems == 'true')
{
$('#followup_items').load("/FollowupItems/Load", function (data, txtStatus, XMLHttpRequest)
{
$('#followup_items').dialog('open');
}
});
});
In this example /FollowupItems/Load is the URL to the proper controller/action that generates the data for the view. You are correct, the view for this would be a partial view, loaded into the empty followup_items div on the page.
So you can use the #ViewBag object anywhere in the view, in this case passing in your boolean indicating if the modal should be loaded/opened. I have not found a way to use ViewBag in an external javascript file, so I typically use embedded script tags in my views so I can use the ViewBag.
You could also add in the user id in the same way (/FollowupItems/Load/#ViewBag.Userid), or any other data the followup action needs.
Basically, I started working on this app knowing nothing about web development which is severely inhibiting my search-fu. Probably should read a book, but that's not likely. Using ASP.NET MVC3 RC2, I'm trying to make a strongly typed partial view which can navigate to related items, as well as maintaining a bread crumb trail (which I thought would be a List in the ViewBag?). A good analogy would be a dictionary page with a thesaurus sub-view.
class Entry
{
string Name;
string Definition;
IEnumerable<Entry> Synonyms;
}
Primarily the page shows the word and its definition, etc. But there's a div with synonyms that you can click to see the selected word's synonyms, replaced w/ ajax.
I was initially thinking I needed to do an html helper, but then I saw stuff about returning PartialView from my controller which seems a lot better.
I'm having trouble piecing together all the pieces of the puzzle. A sample or outline would be great.
Thanks!
Man, I knew I should have worked on it a little longer before asking.
So, here's the recipe:
Make a function in the controller, Synonym(id) { return PartialView(GetEntry(id)); }
Make a partial view, Synonym.cshtml, strongly typed to Entry.
Display the partial view in your main display with <div id="Synonyms">#{Html.RenderAction("Synonym", #Model.Id);}</div>
For the ajax navigation link inside Synonym.cshtml, use something like this
#foreach(Entry syn in #Model.Synonyms)
#Ajax.ActionLink((string)#syn.Name, "Synonym",
new { id = #syn.Id }, new AjaxOptions { UpdateTargetId = "Synonyms" })
One thing that briefly tripped me up was the new { id = #syn.Id } because the parameter name in my controller was actually number, I had to use new { number = ... }
Oh, and I asked about navigation. I think the browser's back button will be sufficient for most navigation, but still wanted a "Back to Current Word" link. For that I did the following:
Modified Controller.Synonym to take another parameter, int orig and set ViewBag.OrigId = orig; before returning.
Modified the ActionLinks to say new { id = #syn.Id, orig = #ViewBag.OrigId }
Created the back link inside Synonym.cshtml - #Ajax.ActionLink("Back To Current Word", "Synonym", new { id = #ViewBag.OrigId, orig = #ViewBag.OrigId }, new AjaxOptions { UpdateTargetId = "Synonyms" })
Modified the call to #Html.RenderAction to pass an object like in the ActionLinks new { id = #Model.Id, orig = #Model.Id }
If someone else comes up with a better answer that makes me want to rewrite my stuff, I'll accept theirs instead. And I'd love feedback on whether I'm missing anything, like how I could avoid the second parameter to Controller.Synonym or other simplifications or improvements.
I'm having trouble determining where to place navigation for an MVC app. For example, say you have the following structure:
Conferences
South Eastern Conference
Florida Gators
Georgia Bulldogs
Arkansas Razorbacks
Pac-10
USC
Hawaii
Big East etc...
How would you best create a structure for implementing a 'main' navigation and subsequent 'sub' navigation? Using the hypothetical example, You'd have specific sub navigation for each conference, showing its respective colleges (and only that conferences colleges).
Is this something you'd handle in the main view and just hide the non-selected conference?
Or would you create a menu helper (or yet another partial) and call that from each individual college's view?
Best way is to use multiple, nested master pages. e.g. Site.master would contain your top-level nav (list of conferences?) then you'd have a different master page for each conference that would 'extend' site.master. You can, in theory, have as many nested master pages as you want. Finally, Florida Gators etc would be 'real' views (i.e. non-master pages).
The tricky part is telling any parent master page which navigation item is currently selected. Because you can't bind master pages to the ViewModel you'll have to use the View Dictionary e.g. View["SelectedMainNavItem"].
Why not use some global layout template that always displays the main navigation, and relies on some helper to render the subnav? (The helper may be superfluous -- you might just output the subnavigation inline in the layout template)
Your controller passes current category/sub-category, and some data structure describing the current subnavigation options, to the view.
After contemplating this issue for a while along with the suggestions, I came up with this solution. Since my subnavigation will always be below the main navigation, I decided to go with the Convention over Configuration method.
In my Site.Master, I have the following two render partials. One displays the main navigation and the other makes a call to BuildSubNavigation to display get the name of a partial to render:
<% Html.RenderPartial("_MainNavigation"); %>
<% var submenu = ViewContext.BuildSubNavigation();
if (submenu != null) {
Html.RenderPartial(submenu);
}%>
Granted, this could be thrown into a Helper, and I intend to do that, this is more explicit and aids in the understanding of the issue.
What this does is call the BuildSubNavigation method. It goes with the convention that if a controller is to have a specific sub navigation, there will be a partial in the form of "_Navigation" So in the spirit of the example, one partial would be "_SouthEasternConferenceNavigation" What I do is then check to see if the current view actually exists. If it does, I return the name, where it's then used to render the partial.
public static string BuildSubNavigation(this ViewContext vc) {
var controller = vc.RouteData.Values["controller"] ?? "";
var viewName = "_" + controller + "Navigation";
if (ViewExists(vc.Controller.ControllerContext, viewName, null)) {
return viewName;
} else {
return null;
}
}
And this is the method that checks whether the View actually exists against the current View Engine:
public static bool ViewExists(ControllerContext cc, string viewName, string masterName) {
if (ViewEngines.Engines.FindView(cc, viewName, masterName).View != null) {
return true;
} else { return false; }
}
I'm unsure if this is the best way to do this, but it's working rather well for a small project I'm currently working on.
Thanks for the answers!