In MVC 4 application I want when click a link, to show some related Products list in lightbox. I have method returns products I need:
public ActionResult GetRelatedProducts(int id)
{
var realProducts = GetRelatedProducts(id);
List<object> productsObjectList = new List<object>();
foreach (var item in realProducts)
{
productsObjectList .Add(new
{
id = item.Id,
fullname = item.Name
});
}
return Json(productsObjectList , JsonRequestBehavior.AllowGet);
}
HTML is:
<a class="show" id="show">Show</a>
<div id="productBox" style="display: none;">
// Product list will get here
</div>
And script:
$('#show').click(function (e) {
url = '#Url.Action("GetRelatedProducts", "Product")';
var data = { id: '#Model.Id' };
$.post(url, data, function (result) {
$('#productBox').lightbox_me({
onLoad: function () {
//How to send returned product list to light box, to show them by foreach loop
}
});
e.preventDefault();
});
});
How can I send product list to productBox to show products?
You code:
$('#show').click(function (e) {
url = '#Url.Action("GetRelatedProducts", "Product")';
var data = { id: '#Model.Id' };
$.post(url, data, function (result) { // <- "result" will contain array
$('#productBox').lightbox_me({
onLoad: function () { ... }
});
e.preventDefault(); // <- this must prevent "a" tag, put it outside
});
});
You could use your list on client side like this:
$.post(url, data, function (result) {
var list = '<ul>';
for(var i = 0; i < result.length; i++)
{
list += '<li>' + result[i].fullname + '</li>';
}
list += '</ul>';
$('#productBox').html(list).lightbox_me();
});
OR as Vladimir Bozic wrote, just use PartialViewResult, from controller return PartialView, it is like normal view, but without layout, just html block and you can use it like:
$.post(url, data, function (result) {
$('#productBox').html(result).lightbox_me();
});
Related
I am still learning jQuery/json and am struggling to figure out how to include optgroups when building my DropDownList via jQuery using json data.
Here is an example of the json data:
0:
Disabled: false
Group:
Disabled: false
Name: "Property Overview"
Selected: false
Text: "Number of Floors"
Value: "277"
Currently, I am able to populate the DropDownList with the Text and Value. That is fairly straight forward. Here is my code for that:
$(document).ready(function () {
$("#PropertyList").on('change', function () {
$("#Options_Question").empty();
var id = $("#PropertyList").val();
var url = '#Url.Action("GetPropertyTypeSpecificQuestions", "Report", new { id = "replaceToken" })';
url = url.replace("replaceToken", id);
$.getJSON(url, null, function (data) {
$("#Options_Question").addQuestions(data);
});
});
$.fn.addQuestions = function (data) {
return this.each(function () {
var list = this;
$.each(data, function (index, questionData) {
var option = new Option(questionData.Text, questionData.Value);
list.add(option);
});
});
}
});
How can I edit my jQuery to include the values from Group.Name and group the questions into their respective optgroups?
I was able to get this working using information found in various places around stackoverflow. Here is the working jQuery:
$(document).ready(function () {
$("#PropertyList").on('change', function () {
$("#Options_Question").empty();
var id = $("#PropertyList").val();
var url = '#Url.Action("GetPropertyTypeSpecificQuestions", "Report", new { id = "replaceToken" })';
url = url.replace("replaceToken", id);
$.getJSON(url, null, function (data) {
$("#Options_Question").addQuestions(data);
});
});
$.fn.addQuestions = function (data) {
var prevGroup, prevGroupName;
$.each(data, function () {
if (this.Group.Name == null) {
$("<option />").val(this.Value).text(this.Text).appendTo("#Options_Question");
}
else if (prevGroupName != this.Group.Name) {
prevGroup = $('<optgroup />').prop('label', this.Group.Name).appendTo('#Options_Question');
}
$("<option />").val(this.Value).text(this.Text).appendTo(prevGroup);
prevGroupName = this.Group.Name;
});
}
});
I currently have a function used to get a list of 5 website names (title) as well as 5 urls
The code below is pulling the list of 5 titles but how would I go about append the title so that it will redirect to the url on click
function getFavorites() {
$.getJSON("/Home/UserFavorites", function (result) {
var options = $("#userfavorites");
List = "";
$('#userfavorites >option').remove();
$.each(result, function () {
options.append($("<option />").val(this.url).text(this.title));
List = List + "," + this.title;
});
}).complete(function () {
$.unblockUI();
});
}
$("#userfavorites").change(function(){
window.location.href = $(this).val();
});
#Html.DropDownList("GroupCode",(IEnumerable<SelectListItem>)ViewBag.GroupCode,"-- Please Select --", new{#id="groupcd"})
DropDownList to select group and post back the value selected to JSON to get a list of clientcode and put into another DropDownList
$(function() {
$("#groupcd").change(function () {
var selectedValue = $("#groupcd").val();
$.post('#Url.Action("getClientCD", "OutstandingClaim")', { selection: selectedValue }, function (data) {
$("#clientcd").html(data);
});
});
});
Javascript to get the selected value and post to action
public JsonResult getClientCD(string selection)
{
var data = db.Common_CustMas.Where(c => c.Group == selection)
.ToList().Select(x => string.Format("{0}--{1}", x.CUSTCODE, x.CUSTNAME));
ViewBag.ClientCode = data;
return Json(data, JsonRequestBehavior.AllowGet);
}
after post back to controller, query the list out and pass back
#Html.DropDownList("ClientCD", (IEnumerable<SelectListItem>) ViewBag.ClientCode, "--Please Select --", new{#id="clientcd"})
The query works, but no data was passed back to the ViewBag client code. Anyone know what problem and how to solve this?
you can do this way
$('#CityID').change(function () {
var cityid = $(this).val();
$.ajax({
url: '#Url.Action("PopulateDistrictsList ","Controller")',
data: { CityID: cityid },
datatype: "json",
success: function (data) {
var ddldist = $('#DistrictID');
$.each(data, function (val, text) {
ddldist.append(
$('<option></option>').val(val).html(text)
);
});
},
})
});
finally it solved with the code
$(function() {
$("#groupcd").change(function () {
var selectedValue = $("#groupcd").val();
$.getJSON('#Url.Action("getClientCD", "OutstandingClaim")', { selection: selectedValue }, function (result) {
var ddl = $('#clientcd');
ddl.empty();
$(result).each(function () {
ddl.append(
$('<option/>').html(this.Text)
);
});
});
});
});
controller
public JsonResult getClientCD(string selection)
{
var data = (from a in db.Common_CustMas
where a.Group == selection
select new {Text = ( a.CUSTCODE + "-" + a.CUSTNAME)}).Distinct().ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
dropdownlist
#Html.DropDownList("GroupCode",(IEnumerable<SelectListItem>)ViewBag.GroupCode,"-- Please Select --", new{#id="groupcd"})
#Html.DropDownList("ClientCD", new SelectList(Enumerable.Empty<SelectListItem>()),new{#id="clientcd"})
I am having trouble updating my HTML UI.
When the document load and calls "getAllProducts()", the HTML UI displays all my items and with the right css class for 'styleStatusCss', and the right 'displayName', the problem is that when I try to update my observableArray with a newly updated product (product name or status has changed), the html UI does not update and remains the same
So here is a quick list of what is happening:
getUpdatedProducts() is called every 25 sec, and returns, any product
that has been updated
I check how many products my observable array has: appVM.itemList.length and it does have 100 (as expected!), I also check that the json product that has been sent back has some modified data, and indeed it has changed!
I then create the javascrip obj MyProduct using that product json object
Now I add my newly created javascript obj MyProduct to the observablearray: appVM.itemList.push(newUpdatedProduct);
And finally I check how many items my observablearray has, after doing the push, (and since I cannot see any changes on the HTML UI), and appVM.itemList.length now says 101 !!! How can that be? the HTML UI still displays the data as it was after the initial load
Please see below most of the code
HTML
<table >
<tbody data-bind="foreach: itemList">
<tr>
<td>
<div data-bind="css: styleStatusCss"></div>
</td>
<td>
<div data-bind="text: displayName"></div>
</td>
</tr>
</tbody></table>
And here is the javascript:
<script type="text/javascript">
var appVM;
var initializeItems = false;
$.ajaxSetup({
// Disable caching of AJAX responses
cache: false
});
$(document).ready(function () {
getAllProducts();
});
setInterval(function () {
if (initializeItems) {
getUpdatedProducts();
}
}, 25000);
function getAllProducts() {
var url = '#Url.Action("_AllProducts", "Home")';
$.ajax({
url: url,
type: 'GET',
dataType: 'JSON',
})
.success(function (result) {
initializeItems = true;
appVM = new AppViewModel();
var mappedProducts = ko.utils.arrayMap(result.ItemList, function (item) {
var con = new MyProduct(item);
return con;
});
appVM.itemList = mappedProducts;
ko.applyBindings(appVM);
})
.error(function (xhr, status, error) {
alert("FATAL ERROR");
})
}
function getUpdatedProducts() {
var url = '#Url.Action("_UpdateProducts", "Home")';
$.ajax({
url: url,
type: 'GET',
dataType: 'JSON',
})
.success(function (result) {
if (result.HasNewData) {
alert("we have some data");
alert("START COUNT: " + appVM.itemList.length); //this shows all my 100 products -> START COUNT: 100
alert("Number of new items: " + result.ItemList.length); // i only get one product back for easy debugging
for (index = 0; index < result.ItemList.length; ++index) {
var updatedProdJson = result.ItemList[index]; //get the json for the product
alert("New prod json: " + objToString(updatedProdJson)); //just for debugging print out in a readable format
var newUpdatedProduct = new MyProduct(updatedProdJson);//create our MyProduct object (which has all properties as observable)
appVM.itemList.push(newUpdatedProduct); //add our new MyProduct to the list
alert("FINAL COUNT: " + appVM.itemList.length); // --> FINAL COUNT: 101
}
}
})
.error(function (xhr, status, error) {
alert("Error: " + status);
})
}
function AppViewModel() {
var self = this; //so it references the viewModel object
self.itemList = ko.observableArray([]);
self.doAlert = function () {
alert("HERE");
}
}
function MyProduct(data) {
//alert("DATA: " + objToString(data));
this.Id = ko.observable( data.Id);
this.Name = ko.observable(data.Name);
this.status = ko.observable(data.Status);
this.displayName = ko.computed(function () {
var fullnmae = this.Id() + " " + this.Name();
return fullnmae;
}, this);
this.styleStatusCss = ko.computed(function () {
var pStatus = 'divstatusnone';
if (this.status() === 'H')
pStatus = 'divlowstatus';
if (this.status() === 'D')
pStatus = 'divhighstatus';
return pStatus;
},this);
}
function objToString (obj) {
var str = '';
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
str += p + '::' + obj[p] + '\n';
}
}
return str;
}
Hope somebody can tell me where i went wrong.
Many thanks,
in getAllProducts, you're assigning the results to itemList, losing your observable array:
appVM.itemList = mappedProducts;
you need to do this instead:
appVM.itemList(mappedProducts);
I'm testing MVC for a demo and I managed to scrap together some pieces but now I am having trouble with an Html.ActionLink. The intent is to present the user with a series of dropdownlists that they must select before the ActionLink is shown. To do that I've copied some JQuery to hide/show my dropdownlists (as selections are made) and the ActionLink. I added an alert to my JQuery to check my values and via the alert it all looks good. But if I debug the controller the parm values are defaulted to 0. I'm not sure what code to include but I will try to include the relevant parts. I think it's something basic.
Here are the dropdown lists and ActionLink.
#Html.DropDownListFor(m => m.selected_env_ID, new SelectList(Model.Environments, "env_ID", "env_DESC"), "*Select an environment")
#Html.DropDownListFor(m => m.selected_app_ID, new SelectList(Model.Applications, "app_ID", "app_DESC"), "*Select an application",new { #hidden = "hidden" })
#Html.DropDownListFor(m => m.selected_job_ID, Enumerable.Empty<SelectListItem>(), "*Select a job", new { #hidden = "hidden" })
#Html.ActionLink("Submit", "Submit", new { id = Model.selected_job_ID, envid = Model.selected_env_ID }, new {id = "lnkSubmit" })
Here is the convoluted JQuery to hide/show and fill the cascading dropdowns.
<script>
$(document).ready(function ()
{
//Dropdownlist Selectedchange event
$("#selected_app_ID").change(function () {
var id = $('#selected_app_ID').val(); // id value
if (id == 0) {
$('#selected_job_ID').hide();
} else {
$('#selected_job_ID').show();
$("#selected_job_ID").empty();
$.ajax({
type: 'POST',
url: '#Url.Action("SelectJobs")',
dataType: 'json',
data: { id: $("#selected_app_ID").val() },
success: function (jobs) {
// jobs contains the JSON formatted list of jobs passed from the controller
$("#selected_job_ID").append('<option value=0>*Select a job</option>');
$.each(jobs, function (i, job) {
$("#selected_job_ID").append('<option value="'
+ job.job_ID + '">'
+ job.job_DESC + '</option>');
});
},
error: function (ex) {
alert('Failed to retrieve jobs.' + ex);
}
});
}
return false;
});
//ddl select change
$("#selected_env_ID").change(function () {
var name = $('#selected_env_ID option:selected').text(); //Item1
var id = $('#selected_env_ID').val(); // id value
if (id == 0) {
$('#divSubmit').hide();
$('#selected_app_ID').hide();
$('#selected_job_ID').hide();
} else {
$('#selected_app_ID').show();
}
});
//ddl select change
$("#selected_job_ID").change(function () {
var name = $('#selected_job_ID option:selected').text(); //Item1
var id = $('#selected_job_ID').val(); // id value
var envid = $('#selected_env_ID').val(); // id value
if (id == 0) {
$('#divSubmit').hide();
} else {
$('#divSubmit').show();
alert("envid=" + envid + " jobid=" + id);
}
});
}); // end document ready
</script>
My controller has this and id and envid end up being 0:
public ActionResult Submit(int id = 0,int envid = 0) {
If I need to include something else just let me know.
Here is the method that fills the job dropdown list. This works without issues. It's the Html.ActionLink call to Submit that fails to include the parameters.
public JsonResult SelectJobs(int id)
{
db.Configuration.ProxyCreationEnabled = false;
IEnumerable<t_job> jobs = db.t_job.Where(j => j.app_ID == id).ToList();
return Json(jobs);
}
Your link
#Html.ActionLink("Submit", "Submit", new { id = Model.selected_job_ID, envid = Model.selected_env_ID }, new {id = "lnkSubmit" })
is rendered on the server side before you make any selection in the dropdowns. If the initial values of selected_job_ID and selected_env_ID are zero or null, then those values will be passed to the controller (have a look at the rendered html).
If you want to pass the values selected in you drop downs, you could either modify the links href attribute in the drop down change events, or create a button instead of a link, and do a redirect in the buttons click event based on the dropdown values.
You need to use JSON.stringify():
data: JSON.stringify({ id: $("#selected_app_ID").val() }),