I have a View on which I would like to display list of partial Views with the HighChart inside.
Controller:
public ActionResult PartialChart(String lName)
{
ReportDict = TempData["Report_Dict"] as Dictionary<ReportElement, List<Shift>>;
DotNet.Highcharts.Highcharts chart = new DotNet.Highcharts.Highcharts("chart")
.SetTitle(new Title { Text = lName + " Output" })
.SetXAxis(new XAxis
{
Categories = HCharExt.getCategoriesDate(ReportDict)
})
.InitChart(new Chart { Width = 500, Height = 300 })
.SetSeries(new Series
{
Name = lName + " Output",
Data = new Data(HCharExt.getLineSerie(ReportDict, "output", lName))
});
return PartialView(chart);
}
View:
#{
ViewBag.Title = "CompleteReport";
}
<h2>Report</h2>
<ul>
#foreach (var l in ViewBag.RepDict)
{
<li>
#Html.Action("PartialChart", "Report", new { lName = l.Key.Line.Name })
</li>
}
</ul>
If I run it, it works but only one Chart (partial View) loads, the last one in the dictionary RepDict. I'm assuming that it loads all of the charts to the same partial View and only last one persist.
How do I load each chart to the new instance of partial View?
Or how should I edit my code to get few same type charts on one page but with different data.
Many Thanks
Solved using different names for each instance of a chart.
Related
i have a list of products in my web page whose details are shown in modal popup.
I tried using the custom tag of statcounter as shown on their site [http://statcounter.com/support/knowledge-base/276/] but it works only for one product category. I am using the same modal body to show different products.
following is the codesnippet :
var sc_project = $##$##;
var sc_invisible = 0;
var sc_security = "$#*$*##$";
var _statcounter = _statcounter || [];
//function to push custom statcounter for products_of_interest
function _productStatCounter(product_of_interest) {
_statcounter.push({ "tags": { "data-project": product_of_interest } });
}
// jquery to push projects based on click
$(".portfolio-link").click(function () {
test_product = ($(this).attr("href"));
if(test_product !== undefined){
product_of_interest = ($(this).attr("data-project"));
_productStatCounter(product_of_interest);
} else {
return;
}
});
I used jquery to push the product_of_interest based on click of the product but statcounter is showing info about only one product not all the products. Since my product web app is a single page so i have used modal-body for showing different products on a popup screen. Is there any way to use statcounter on popups ?
The following worked for me. My window's hash changes when I open a modal and I was able to push the tags to statcounter on hash change.
<script type="text/javascript">
var sc_project = ******;
var sc_invisible = 1;
var sc_click_stat = 2; /*track anchor links*/
var sc_security = '******';
var _statcounter = _statcounter || [];
_statcounter.push({ tags: { page: 'homepage' } }); /*optional*/
window.onhashchange = locationHashChanged;
function locationHashChanged() {
var modalName = window.location.hash;
_statcounter.push({ tags: { project: modalName } });
_statcounter.record_pageview();
}
</script>
In my Kendo grid I am trying to put the 'create new item' button in the header (title) of the command column instead of the toolbar. Here is part of my grid definition:
var grid = $("#grid").kendoGrid({
columns: [{ command: { name: "edit", title: "Edit", text: { edit: "", cancel: "", update: "" } },
headerTemplate: "<a onclick ='NewItemClick()' class='k-button k-button-icontext k-create-alert' id='new-item-button' title='Click to add a new item'><div>New Item</div></a>"},
My question is: how to create a new row and put that row in edit mode in 'NewItemClick()'
There are some troublesome scope issues when you try to bind the click event in the template definition itself.
Instead, it is easier to assign the link an ID, and then bind the click event later. Notice that I've given it id=create.
headerTemplate: "<a id='create' class='k-button k-button-icontext k-create-alert' id='new-item-button' title='Click to add a new item'><div>New Item</div></a>"
Then in document ready, I bind the click event:
$("#create").click(function () {
var grid = $("#grid").data("kendoGrid");
if (grid) {
//this logic creates a new item in the datasource/datagrid
var dataSource = grid.dataSource;
var total = dataSource.data().length;
dataSource.insert(total, {});
dataSource.page(dataSource.totalPages());
grid.editRow(grid.tbody.children().last());
}
});
The above function creates a new row at the bottom of the grid by manipulating the datasource. Then it treats the new row as a row "edit". The action to create a new row was borrowed from OnaBai's answer here.
Here is a working jsfiddle, hope it helps.
I would like to complete on gisitgo's answer. If your datasource takes some time to update, when calling page(...), then the refresh of the grid will cancel the editor's popup. This is averted by binding the call to editRow to the "change" event :
var grid = $("#grid").data("kendoGrid");
if (grid) {
//this logic creates a new item in the datasource/datagrid
var dataSource = grid.dataSource;
var total = dataSource.data().length;
dataSource.insert(total, {});
dataSource.one("change", function () {
grid.editRow(grid.tbody.children().last());
});
dataSource.page(dataSource.totalPages());
}
NB: This approach will yield problems if your grid is sorted because the new row will not necessarily be at the end
I have found that issues might appear if you have multiple pages, such as the inserted row not opening up for edit.
Here is some code based on the current index of the copied row.
We also edit the row based on UID for more accuracy.
function cloneRow(e) {
var grid = $("#grid").data("kendoGrid");
var row = grid.select();
if (row && row.length == 1) {
var data = grid.dataItem(row);
var indexInArray = $.map(grid.dataSource._data, function (obj, index)
{
if (obj.uid == data.uid)
{
return index;
}
});
var newRowDataItem = grid.dataSource.insert(indexInArray, {
CustomerId: 0,
CustomerName: null,
dirty: true
});
var newGridRow = grid.tbody.find("tr[data-uid='" + newRowDataItem.uid + "']");
grid.select(newGridRow);
grid.editRow(newGridRow);
//grid.editRow($("table[role='grid'] tbody tr:eq(0)"));
} else {
alert("Please select a row");
}
return false;
}
I just want to place a dropdown list on my page and when i select any page number from dropdownlist , it should display appropriate page from webgrid. MVC3
//For displaying Dropdown List...
#{
int i = 1;
<select id="number">
#for (i = 1; i < 6; i++)
{
<option value=#i>
#i
</option>
}
</select>}
//Jquery for navigating on page selected by dropdownlist...
<script language="javascript">
$(document).ready(function () {
$("#number").change(function () { // Number is the name of dropdownlist control
var selectedvalue = $('#number').val(); // Value selected by control
value = '/student?page=' + selectedvalue; // Here student is my controller name
$('#editlink').attr('href', value); // For rendering on a Action Link.
});
});</script>
//Action Link.....
#Html.ActionLink("Go", "student", "page=", new { ID = 0 }, new { id = "editlink" })
// edit link is the link name used in Jquery.
I have a drop down list that I need to react to asynchronously. I cannot get the Ajax.BeginForm to actually do an asynchronous postback, it only does a full postback.
using (Ajax.BeginForm("EditStatus", new AjaxOptions { UpdateTargetId = "divSuccess"}))
{%>
<%=Html.DropDownList(
"ddlStatus",
Model.PartStatusList.OrderBy(wc => wc.SortOrder).Select(
wc => new SelectListItem
{
Text = wc.StatusDescription,
Value = wc.PartStatusId.ToString(),
Selected = wc.PartStatusId == Model.PartStatusId
}),
new { #class = "input-box", onchange = "this.form.submit();" }
)%>
<div id='divSuccess'></div>
<%
}
When the user selects an item from the list, it does a full postback and the controller method's return value is the only output on the screen. I am expecting the controller method's return value to be displayed in "divSuccess".
[AjaxAwareAuthorize(Roles = "Supplier_Administrator, Supplier_User")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditStatus(PartPropertiesViewModel partPropertiesViewModel)
{
var part = _repository.GetPart(partPropertiesViewModel.PartId);
part.PartStatusId = Convert.ToInt32(Request.Form["ddlStatus"]);
_repository.SavePart(part);
return Content("Successfully Updated Status.");
}
How about doing this the proper way using jQuery unobtrusively and getting rid of those Ajax.* helpers?
The first step is to use real view models and avoid the tag soup in your views. Views should not order data or whatever. It's not their responsibility. Views are there to display data that is being sent to them under the form of a view model from the controller. When I see this OrderBy in your view it's just making me sick. So define a clean view model and do the ordering in your controller so that in your view you simply have:
<% using (Html.BeginForm("EditStatus", "SomeControllerName", FormMethod.Post, new { id = "myForm" }) { %>
<%= Html.DropDownListFor(
x => x.Status,
Model.OrderedStatuses,
new {
#class = "input-box",
id = "myDDL"
}
) %>
<% } %>
<div id="divSuccess"></div>
and finally in a completely separate javascript file subscribe for the change event od this DDL and update the div:
$(function() {
$('#myDDL').change(function() {
var url = $('#myForm').attr('action');
var status = $(this).val();
$.post(url, { ddlStatus: status }, function(result) {
$('#divSuccess').html(result);
});
});
});
This assumes that in your controller action you would read the current status like this:
[AjaxAwareAuthorize(Roles = "Supplier_Administrator, Supplier_User")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditStatus(PartPropertiesViewModel partPropertiesViewModel, string ddlStatus)
{
var part = _repository.GetPart(partPropertiesViewModel.PartId);
part.PartStatusId = Convert.ToInt32(ddlStatus);
_repository.SavePart(part);
return Content("Successfully Updated Status.");
}
And when you see this you might ask yourself whether you really need a form in this case and what's its purpose where you could simply have a dropdownlist:
<%= Html.DropDownListFor(
x => x.Status,
Model.OrderedStatuses,
new Dictionary<string, object> {
{ "class", "input-box" },
{ "data-url", Url.Action("EditStatus", "SomeControllerName") },
{ "id", "myDDL" }
}
) %>
<div id="divSuccess"></div>
and then simply:
$(function() {
$('#myDDL').change(function() {
var url = $(this).data('url');
var status = $(this).val();
$.post(url, { ddlStatus: status }, function(result) {
$('#divSuccess').html(result);
});
});
});
I'm developing a web application using MVC 3 RTM. In a view I have a WebGrid which works fine with sorting and paging. However, I also needed some filtering support on the page, so I added a textbox and a checkbox. The view code looks like this:
#using (Html.BeginForm("Index", "Customer", FormMethod.Get))
{
<fieldset>
<legend>Filter</legend>
<div class="display-label">
Search for</div>
<div class="display-field">#Html.TextBox("filter", null, new { onchange = "$('form').submit()" })</div>
<div class="display-label">
Show inactive customers?
</div>
<div class="display-field">
#Html.CheckBox("showInactive", false, new { onchange = "$('form').submit()" })
</div>
</fieldset>
var grid = new WebGrid(canPage: true, canSort: true, ajaxUpdateContainerId: "grid", rowsPerPage: 10, defaultSort: "Name");
grid.Bind(Model, rowCount: Model.Count, autoSortAndPage: false);
grid.Pager(WebGridPagerModes.All);
#grid.GetHtml(htmlAttributes: new { id = "grid" },
columns: grid.Columns(
grid.Column("Name", "Name"),
grid.Column("Address", "Address"),
grid.Column("IsActive", "Active", (item) => item.IsActive ? "Yes" : "No")));
}
This works fine except when I check the checkbox. When I load the page for the first time, the checkbox is not checked. Sorting and paging works, and I can enter some text as a filter and it filters my result, and sorting and paging still works after that. However, if I check the checkbox, it updates the result, but sorting no longer works. The filter still works though, so if I enter some text, it correctly filters the result and still respects the checkbox.
I've tried setting a breakpoint in my controller, and there's no problem there. The request is sent when I try to sort, and the controller correctly returns the view with the result as the model. But it doesn't seem like the WebGrid is updating itself.
Has anyone else experienced this, or has anyone some good advice on what to look for?
Thanks!
I normally add a form (above my WebGrid) which contains a textbox called "Keywords" and a checkbox called "IsActive" and when the "Go" button is clicked it reloads the WebGrid adding the "Keywords" and "IsActive" options to the query string.
You can add more elements to your form and their values will be sent al
Use the following helper script - webgrid.helper.js:
function reloadGrid(form) {
var grid = form._grid ? form._grid.value : "grid";
var args = {};
updateQueryParams(args, grid + " th a");
args.sort = "";
args.sortdir = "";
updateQueryParams(args, grid + " tfoot a");
args.page = 1;
for (var i = 0; i < form.elements.length; i++) {
var el = form.elements[i];
if (el.type == "text" || el.type == "select" || (el.type == "radio" && el.checked))
args[el.name] = el.value;
else if (el.type == "checkbox")
args[el.name] = el.checked;
}
//get controller name
var s = $("#grid th a")[0].onclick.toString();
s = s.substring(s.indexOf("/"));
var controller = s.substring(0, s.indexOf("?"));
var queryString = "";
for (var key in args)
queryString += "&" + key + "=" + escape(args[key]);
var url = controller + "?" + queryString.substring(1);
$("#" + grid).load(url + " #" + grid);
}
function updateQueryParams(args, path) {
var links = $("#" + path);
if (links.length == 0)
return;
var s = links[0].onclick.toString();
s = s.substring(s.indexOf("?") + 1);
s = s.substring(0, s.indexOf(" #"));
var a = /\+/g; // Regex for replacing addition symbol with a space
var r = /([^&=]+)=?([^&]*)/g;
var d = function (s) { return decodeURIComponent(s.replace(a, " ")); };
var q = s;
while (e = r.exec(q))
args[d(e[1])] = d(e[2]);
}
Then just above my webgrid, I have the following partial file - *_ListFilter.cshtml*
#using (Html.BeginForm(null, null, FormMethod.Get))
{
<div id="filter">
<table width="600">
<tr>
<td>#Html.TextBoxFor(c => c.Keywords, new { size = 50, placeholder = Strings.SearchByKeywords, title = Strings.SearchByKeywords })</td>
<td>