Showing System.Web.Helpers.Chart in a partial view from the model - c#

So I was trying out the Chart helpers in the System.Web.Helpers namespace.
according to http://www.asp.net/web-pages/tutorials/data/7-displaying-data-in-a-chart
I make the chart in a .cshtml view but I wanted to keep it in the ViewModel instead.
No problem except for when I'm trying to render it as a smaller image in the website.
I thought the cleanest solution would be to create one shared partial view to render graphs from models
_graph.cshtml
#model System.Web.Helpers.Chart
#Model.Write()
And then render this partial view somehow in the proper websites. I tried a few versions but can't seem to get it to work.
Website.cshtml
<div>
<h2>Some header above a graph</h2>
<img src="#Html.Partial("_graph", Model.TheChart)" />
</div>
This doesn't work and I'm not certain how to do this. Only think I can think of now is making all models with charts inherit an Interface that exposes Chart and let that be the model for _graph.cshtml.
<img src="_graph.cshtml" />
But not sure if the this uses the Model.
Any opinions?

<div>
<h2>Some header above a graph</h2>
<img src="#Url.Action("DrawChart")" />
</div>
and then you could have a controller action:
public ActionResult DrawChart()
{
MyViewModel model = ...
return View(model);
}
and a corresponding view that will draw the chart (DrawChart.cshtml):
#model MyViewModel
#{
// TODO: use the data from the model to draw a chart
var myChart = new Chart(width: 600, height: 400)
.AddTitle("Chart Title")
.AddSeries(
name: "Employee",
xValue: new[] { "Peter", "Andrew", "Julie", "Mary", "Dave" },
yValues: new[] { "2", "6", "4", "5", "3" })
.Write();
}
and the rendered result:

<div>
<h2>Some header above a graph</h2>
<img src="#Url.Action("DrawChart")" />
</div>
public ActionResult DrawChart()
{
MyViewModel model = ...
return View(model);
}
!!! To send the Model parameter to DrawChart
Change to
<div>
<h2>Some header above a graph</h2>
<img src="#Url.Action("DrawChart",Model)" />
</div>
public ActionResult DrawChart(MyViewModel _MyViewModel )
{
MyViewModel model = MyViewModel ;
return View(model);
}
MyViewModel is Null
Seek advice from those who know.

Related

ASP MVC Razor View doesn't want to show #Html.TextBoxFor value from the model

my razor view is accepting a model ... and I have this code in it ..
#{
var my_value = "wth";
if (Model.app != null)
{ my_value = Model.app.name; }
}
#Html.TextBoxFor(a => a.app.name, new { #Value = my_value })
shows 'wth' when the model isn't null ... did some debugging to see if my_value is set properly ... hmmm
Edit:
Thank you for the comments.
A bit new to ASP MVC. Some background to what I am trying to do:
I have a main view, Main.cshtml, which shows records. Each record can be edited by clicking glyphicon.
JS code grabs the record_id and makes Ajax call to Application Controller / editApp action.
I have a partial, _EditApplication.cshtml, within Main.cshtml, to show my tabbed jQuery UI dialog. And also uses _AddAppForm.cshtml partial that takes a Model to be shown in the data fields.
.... I think this is where my problem is (among others lol)... I am calling the partial (_EditApplication.cshtml) in the main view ... and I am returning the same partial in my Controller Action with an associated model.
Code:
Main.cshmtl
#{ AppDBServer this_ads = new AppDBServer(); }
#Html.Partial("_EditApplication", this_ads)
<div id=#app.app_id.ToString() class="glyphicon glyphicon-pencil btn_edit_app" aria-hidden="true" style="color:blue; cursor:pointer"></div>
JS code in Main.cshtml
$('.btn_edit_app').click(function () {
var app_to_edit = $(this).attr('id');
$.ajax({
url: '/Application/editApp',
contentType: 'application/html; charset=utf-8',
data: { app_id: app_to_edit},
type: 'GET',
dataType: 'html',
success: function (result) {},
});
$('#edit_tabs').tabs({ active: 0 });
$('#edit_dialog').dialog({ width: 700, height: 400 });
});
_EditApplication.cshtml - Partial
#using NameSpace.Models
#model AppDBServer
<div id="edit_dialog" title="Edit Application" style="display: none">
#using (Html.BeginForm("saveApps", "Application", new { isNew = false })) {
<div id="edit_tabs">
<ul><li>Application</li></ul>
#Html.Partial("_AddAppForm", #Model)
</div>
}
</div>
Application Controller - Action: editApp
namespace SHS_Connect.Controllers
{
public class ApplicationController : Controller
{
public ActionResult editApp(int app_id)
{
AppDBServer ads = new AppDBServer();
ads = findADS(app_id);
return PartialView("_EditApplication", ads);
}
}
}
_AddAppForm.cshmtl - Partial used in _EditApplication.cshtml
#using NameSpace.Models
#model AppDBServer
<div id="application">
<div class="form-group">
#Html.LabelFor(a => a.app.name)
#{
var my_value = "wth";
if (Model.app != null)
{ my_value = Model.app.name; }
}
#Html.TextBoxFor(a => a.app.name, new { #Value = my_value })
</div>
</div>
So, yea, I figure it out ... in case someone gets stuck like this ... changes to make:
Main.cshmtl:
adding the partial here doesn't work, have to replace it with a div tag w/id that will contain the partial ...
<div id="div_editapp_dialog"></div>
JS Code in Main.cshtml:
The success function should populate the div and get the tabs / dialog going.
success: function (result) {
$('#div_editapp_dialog').html(result);
$('#edit_tabs').tabs({ active: 0 });
$('#edit_dialog').dialog({ width: 700, height: 400 });
}
No change to _EditApplication.cshtml and the Controller.
Clean up _AddAppForm.cshmtl ...
<div class="form-group">
#Html.LabelFor(a => a.app.name)
#Html.TextBoxFor(a => a.app.name)
</div>

Getting model data without a viewbag

I'm an intern working on some quality-of-life improvements for a site. Nothing essential, but since this is actually going to be deployed I want to keep things tidy.
I need to pull a table from a database, and display it in in a shared header on a site. I already have the database set up, the model getting data from the database, and a test view just to see if it's displaying correctly. However, the model is being passed by the page controller through the viewbag, which I've been told not to do.
So, how can I have my page print out my model data without passing it through a viewbag?
You can do that using this format
public ActionResult Index(YourModelHere model)
{
return View(model);
}
In your view, add this
#model yournamespacehere.Models.YourModelHere
UPDATE
Create a new controller for partial view data
//partial view call
public ActionResult GetHeaderPartial()
{
var model = new DataModel();
model.data1 = "Menu 1";
model.data2 = "Menu 2";
return PartialView("_HeaderPartial", model);
}
Create the Partial View for the shared header. In this example, i've named it as "_HeaderPartial"
#model yournamespace.Models.DataModel
<li>#Model.data1</li>
<li>#Model.data2</li>
In your shared header layout, add #Html.Action("GetHeaderPartial","ControllerHere")
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">#Html.ActionLink("your logo here", "Index", "Home")</p>
</div>
<div class="float-right">
<section id="login">
#Html.Partial("_LoginPartial")
</section>
<nav>
<ul id="menu">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
#Html.Action("GetHeaderPartial","Sample")
</nav>
</div>
</div>
</header>
Here's a good place to start. As the article states, there are basically three ways to pass data to the view:
ViewBag
Dynamic objects
Strongly Typed objects
With the latter approach (generally a good idea), you just have to pass the model instance to the ActionResult you're returning (in your case, that would be a ViewResult instance).
So instead of this....
public ActionResult Index()
{
ViewBag.Foo= new Foo();
return View();
}
you do this...
public ActionResult Index()
{
return View(new Foo());
}
Make sure your model in the Index view has the following line:
#model Foo
Now you can use Razor or whatever syntax you're using to do what you need to do in your view.
Setup a view model that is created in the controller and passed to the view. This link will help you!

Show loading panel on index action of ASPNET MVC

In my ASP.NET MVC 5 web site i have a devexpress navbar with multiple itens, each item have a single unique controller, always when i click on a item the Index action of the corresponding controller is called.
public ActionResult Index()
{
//Load large data and return it into a gridview.
}
While im loading this data i would like to show a loading panel but i dont know where i can do it using in mvc, in aspnet webforms its easier to do something like that.
Any MVC expert could help me with this?
Inside your view you suppose to use am Ajax Form, and to point to your LoadingElementId in it's definition.
Here is an example:
#using (Ajax.BeginForm("FilterNews", "News", null,
new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "container", LoadingElementId = "custom-loading" }))
{
<div id='container'>
//Your helpers #Html.TextBoxFor(x => x.....) or render a partial
</div>
}
<style>
.loading{
position:absolute;
width:100%,
height:100%,
top:0,
left:0,
background:white,
}
</style>
<div id="custom-loading" class="loading">Loading..Please wait...</div>
Also if you want to display a Loader for every XHR Call u may set a binder on ajaxSend event like this :
<div id="ajax-loader-element">
<img src="#Url.Content("~/Content/Images/ajax-loader.gif")"/>
</div>
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery(document).bind("ajaxSend", function () {
jQuery('#ajax-loader-element').show();
}).bind("ajaxComplete", function() {
jQuery('#ajax-loader-element').hide();
});
});
</script>

Select Items and display in same view. Return results to controller

I am new to mvc and fairly young with Javascript so I apologize for the wrong/missing code. I am trying to make a view where the user has a drop down list and items selected via btnAdd will be dynamically displayed in the same view below the btnAdd button. I am assuming the best way to do this would be with JavaScript. After the user has made there choices they will click the btnckout button and there selections will be returned to the controller. Here is what I have so far. I am a little stuck so any help would be appreciated!
View:
#model OnlineTakeout.Models.ProductView
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<script src="~/Scripts/jquery-2.1.0.min.js"></script>
<title>Index</title>
</head>
<body>
#using (Html.BeginForm()){
<div>
Pick Product:
<br />
#Html.DropDownListFor(m=>m.ProductId, Model.Products)
<br />
<p>
<input type="button" value="AddToOrder" id="btnAdd" />
</p>
</div>
}
<div>
#using (Html.BeginForm()) {
//Added Items would display here after individual btnAdd button presses
<p>
<input type="button" value="CheckOut" id="btnChkOut" />
</p>
}
</div>
</body>
<script>
$(function () {
$("#btnAdd").click(addProduct);
})
$(function () {
$("#btnChkOut").click(saveProducts);
})
var productList = [];
var id = $("#ProductId").val();
// This function would also display these items on view
function addProduct() {
productList.push(id);
};
function saveProducts() {
$.post("/Product/Index/" + productList());
}
}
</script>
Controller:
public class ProductController : Controller
{
//
// GET: /Product/
public ActionResult Index()
{
var model = new ProductView();
var products = new List<Product> { new Product { ProductId = 1, Name = "Product One", Price = 1.00m },
{ new Product { ProductId = 2, Name = "Product Two", Price = 2.00m } }};
model.Products = new SelectList(products, "ProductId", "Name");
return View(model);
}
[HttpPost]
public JsonResult Index(int[] prodList)
{
return Json("Index");
}
The way I usually do this is by using jQuery.
You will need to create an event handler in jQuery for the change event of your drop down list that is supposed to trigger this change. When that fired, post to an action in your controller that is going to bind a partial controller and return the partial view. It is important to have a return type of ActionResult - that will return the HTML back to success method of your post. Then just embed the HTML on the page and you are done.

two page layouts into one view

I would like some advice on this matter. I have a view page that will display a number of users. One view is to display users in a grid (gallery like) of their images. Second view is to display the same users but by their name in a list layout. I will have a toggle button on the page to switch between the two. What is the best way to go about it? Having two separate view pages or have a partial view of some sort?
Update Code after suggestion below
<div data-bind="template: {name:'grid-template'}"></div>
<div data-bind="template: {name:'list-template'}"></div>
<script style="float:left" type="text/html" id ="grid-template">
<section " style="width:100%; float:left">
<section id="users" data-bind="foreach: Users">
<div id="nameImage">
<figure id="content">
<img width="158" height="158" alt="Gravatar" data-bind="attr:{src: GravatarUrl}"/>
<figcaption>
<a title="Email" id="emailIcon" class="icon-envelope icon-white" data-bind="attr:{'href':'mailto:' + Email()}"></a>
<a title="Profile" id="profileIcon" class="icon-user icon-white"></a>
</figcaption>
</figure>
<p data-bind="text:Name"></p>
</div>
</section>
</section>
</script>
<script style="float:left" type="text/html" id="list-template">
<div data-bind="foreach: Users">
<div style="width:60%; float:left; margin:10px; height:58px">
<img style="float:left; margin-right:5px" width="58" height="58" alt="Gravatar" data-bind="attr:{src: GravatarUrl}"/>
<p style="height:58px; float:left; vertical-align:central" data-bind="text:Name"></p>
<a style="float:right" title="Profile" class="icon-user icon-black"></a>
<a style="float:right" title="Email" class="icon-envelope icon-black" data-bind="attr:{'href':'mailto:' + Email()}"></a>
</div>
</div>
</script>
Knockout Script File
$.views.User.UserViewModel = function (data) {
var self = this;
self.Name = ko.observable(data.Name);
self.Email = ko.observable(data.Email);
self.ContentRole = ko.observable(data.ContentRole);
self.MD5Email = ko.observable(data.MD5Email);
self.GravatarUrl = ko.computed(function () {
return 'http://www.gravatar.com/avatar/' + self.MD5Email() + '?s=300&d=identicon&r=G';
});
self.renderMode = ko.observable('grid');
self.displayTemplate = ko.computed(function () {
return self.renderMode() + '-layout-template';
});
};
Personally, I like having clean isolated small little Partial Views especially if it is going to be regular HTTP POST.
However, based on the assumptions I am making below, I think I can suggest a better implementation design.
My Assumption
You have
Index.cshtml Parent view to display a list Users.
JSON object array containing your list of Users
Based on what I see, you are using KnockoutJS.
Read the KnockoutJS Template Binding especially the "Note 5: Dynamically choosing which template is used" part.
It kind of makes it easier to do what you are doing if you are using KnockoutJS or something similar.
You simply have toggle between the two rendering templates.
<script type="text/html" id="gallery-layout-template"> ... </script>
<script type="text/html" id="listing-layout-template"> ... </script>
<div id="divOutputContainer"
data-bind="template: { name: displayTemplate, foreach: users }"></div>
<script type="text/javascript">
$(document).ready(function() {
// I am just writing out a dummy User array here.
// Render out your User Array JSON encoded using JSON.NET.
var myUsers = [
{ "id" : 1, "name": "User 1" },
{ "id" : 2, "name": "User 2" }
];
// here is your KnockoutJS View Model "class"
function MyKoViewModel(users) {
var self = this;
self.users = ko.observableArray(users);
// Toggle this renderMode observable's value
// between 'listing' and 'gallery' via your Toggle button click event handler
self.renderMode = ko.observable( 'gallery' );
self.displayTemplate = function(user) {
// this will return 'gallery-layout-template' or 'listing-layout-template'
return self.renderMode() + '-layout-template';
}
}
ko.applyBindings( new MyKoViewModel( myUsers ) );
});
</script>
So with that technique, you don't need to make an AJAX call every time to refresh the view with a different rendering template.
You have all your data that you want to display as a client-side JavaScript KnockoutJS view model.
Then, just switch the client-side rendering template using KnockoutJS.
Must more efficient :-)
NOTE
I have a feeling, you might have to use the ko.computed() for the MyKoViewModel's displayTemplate() function like this.
self.displayTemplate = ko.computed(function() {
return self.renderMode() + '-layout-template';
}

Categories