How to send an array using Url.Action - asp.net

I have an array of integers called data which I would like to send from my View to a specific controller, I could see that i can send integers and strings and it works with the code that I have so far, but when I try to send an array I can get the data correctly.
This is the code that I have in my view, it is something simple just to be in perspective.
function SeeStation() {
var data = [];
var i = 0;
$("input:checkbox:checked").each(function () {
data[i] = $(this).val();
});
window.location.href = "#Url.Action("ExportData", "Dispatch")?id=" + data;
}
and this is the code in the controller. I know it doesn't make much sense but so far I am focused on correctly obtaining the array by parameter.
public ActionResult ExportData(int[] id)
{
var data = cn.ESTACIONDESPACHOes.ToList();
return View(data);
}
In my array data I store something like this [1,2,3] and I would like to get something similar in the controller array id.

It will not bind like that.
To get the id array in your action you need to have the link at the end like this: *Dispatch/ExportData?id=1&id=2&id=3*
Your "#Url.Action("ExportData", "Dispatch")?id=" + data; will not generate that (data will give the numbers separated with commas).
You can just build the query string when you enumerate the checkboxes.
function SeeStation() {
var data = '';
$("input:checkbox:checked").each(function () {
data += 'id='$(this).val() + '&';
});
window.location.href = "#Url.Action("ExportData", "Dispatch")?" + data;
}
You will have a "&" in the end. You can easily remove it, but it will not affect anything.
There may be better ways to do this though, but I just used your function.

try
#Url.Action("ExportData", "Dispatch", new { id= [1,2,3] })

Store the Values in the Hidden Fields
#Html.HiddenFor(m => m.Ids, new { #Value = [1,2,3] })
Then Using the Ajax Get Method Pass the Hidden fields
In the Controller Method Convert the sting to array using string extension method

function SeeStation() {
var data = [];
var i = 0;
$("input:checkbox:checked").each(function () {
data[i] = $(this).val();
});
location.href = '#Url.Action("ExportData", "Dispatch")?id=' + data;
}
Please remove window keyword.

Related

Any way to find out the fields in a datasource?

I'd like to write a script to dump the contents of a given table to a spreadsheet regardless of the fields, (I've done this for several individual tables but want to write something universal).
Will
app.models.filesToCopy.fields._values;
be involved?
I would say the most generic way would be to establish a server function and pass in the model name as a parameter. Then establish a script similar to what I put below. You can even format your data based on the field type if wanted by using fields[n].type in a if or select statement.
function YourFunction(YourModel) {
var sheetfile = SpreadsheetApp.create('test file');
var ss = sheetfile.getActiveSheet();
var fields = app.metadata.models[YourModel].fields;
var results = app.models[YourModel].newQuery().run();
var i, j;
var sheetdata = [], header = [];
for (j in fields) {
header.push(fields[j].displayName);
}
sheetdata.push(header);
for (var i in results) {
var data = [];
for (j in fields) {
data.push(results[i][fields[j].name]);
}
sheetdata.push(data);
}
ss.getRange(1,1,sheetdata.length,fields.length).setValues(sheetdata);
}

Meteor parsing a list of arrays with forEach

I have this helper in Meteor:
itemMenuAddOns: function(_id){
console.log(_id); //OK
var addOns = RestMenuItems.find({_id:_id}, {addOns: 1});
if(addOns){
console.log(addOns); //OK, an object where in the collection/map I see the expected array.
addOns.forEach( function(addOn) { console.log(addOn.title); } )// displays nothing
}
}
The problem is that the forEach console.log displays nothing. In both cases, if I use addOn.title or just even 123, to display.
thanks.
Well I had passed a wrong id and used find instead of findOne.
Now it works. for anyone interested:
itemMenuAddOns: function(_id){
var list = '';
var cursor = RestMenuItems.findOne({_id:_id}, {addOns: 1});
if(cursor){
cursor.addOns.forEach( function(addOn) {
var addOn = RestMenuSideItems.findOne({_id: addOn});
list += Spacebars.SafeString("<div>" + addOn.title + "</div>")});
return list;
}
}

How to bind/referece grand parent property to/inside child knockout

Hi guys looking for some basic advice.
I have four models: BoardViewModel, List, Card, Member
var Member = function (id, name, avatar) {
var self = this;
self.id = id;
self.name = name;
self.avatar = avatar;
self.isChecked = ko.observable(false);
};
I am instantiating members property inside BoardViewModel. But I want to use a copy of this model inside each Card model to instantiate a list of assigned members.
Each card stores comma separated list of member references like
",1,2,4,5"
I am writing a loop to BoardViewModel.members and mark members as checked if id references match bore I assign it as Card.members.
The last piece of the puzzle I am missing is reference to the BoardViwModel.members.
I have a lovely example fiddler that would somewhat help to build a picture of what I am talking about.
Just bear in mind that once I have this working properly I want to replace view() binding
foreach: $root.members
with
foreach: members
If at all possible I would like to avoid passing BoardViewModel.members as parameter into List and then into Card.
Update 1
As suggested by #Jeroen here's a simplified version of my fiddler.
The top view() model which encompases a concept of lists:
var BoardViewModel = function (lists, members) {
var self = this;
// in reality members are fetched via ajax call to the server
// and instantiate as a ko.observableArray()
self.groupMembers = ko.observableArray(members);
self.lists = ko.observableArray(lists);
...
}
In reality this has a signature like this:
var boardViewModel = function (initialData)
moving on.
The child List model which encompases a concept of cards:
var List = function (id, name, cards, sortOrder, groupMembers) {
var self = this;
self.cards = ko.observableArray(cards);
...
}
in reality:
var list = function (item, groupMembers)
nothing special there really.
The child Card model which encompases the concept of card items (but lets not go there yet):
var Card = function (id, title, description, contentItemId, members, groupMembers) {
var self = this;
self.members = ko.observableArray(parseMembers(members));
// now remember each card has a members property
// which stores comma separated list ",1,4"
function (members) {
var memberList = groupMembers;
var memberRefList = members.split(',');
ko.utils.arrayForEach(memberList, function(member){
ko.utils.arrayForEach(memberRefList, function(memberId){
if(member.id === meberId) {
member.isChecked(true);
}
});
});
return memberList;
}
...
}
in reality:
var card = function (item, groupMembers)
nothing too fancy there either.
I currently have something like this working on my dev environment.
Problem:
Those with keen eyes probably noticed the way I was passing groupMembers all the way up. I am not particularly hyped about the idea.
Anyone know a better way of implementing this? i.e. why can't I just do something like
var memberList = self.parent.parent.groupMembers;
for instance.
As per me, the better way to do is to have the child viewmodels inside the parent view-model. like this where you can access the parent data members as well as methods directly.
ViewModel
var BoardViewModel = function(){
var self = this;
this.members = ko.observableArray();
this.lists = ko.observableArray();
// Child View Models
this.Member = function(member){
this.id = member.id;
this.name = member.name;
this.avatar = member.avatar;
this.isChecked = ko.observable(false);
}
this.List = function(list){
// same for this
};
this.Card = function(card){
// same for this
};
// a Method to bind the data with the observables and arrays
// Assuming data is a json object having Members, List objects
this.applyData = function(data){
self.members(jQuery.map(data.Members, function(item){
return new self.Member(item);
}));
self.lists(jQuery.map(data.Lists, function(item){
return new self.List(item);
}));
}
}
onDom ready
// json object holding your data
var data = {
"Members" : [
],
"Lists" : [
],
"Cards" : [
]
};
var vm = new BoardViewModel();
$(function(){
ko.applyBindings(vm, document.getElementById('myModule'));
vm.applyData(data);
});

Is there a way to attach callback what fires whenever a crossfilter dimension filter changes?

I have several charts built with dc.js. I can achieve the desired functionality by attaching a callback to each dc.js chart's .on("filterted", function(chart) {}) but this is annoying because I have to attach the same callback to each chart. And error prone because as new charts are added, someone has to remember to attach an event hander. I would prefer to just attach a callback to the underlying crossfilter. Is that possible?
Is there a way to optimize this...
var ndx = crossfilter(data);
var dimAlpha = ndx.dimension(function(d) {return d.alpha});
var dimBeta = ndx.dimension(function(d) {return d.beta});
var groupAlpha = dimAlpha.group().reduceSum(function(d) {return 1;});
var groupBeta = dimBeta.group().reduceSum(function(d) {return 1;});
dc.pieChart(myDomId1)
.dimension(dimAlpha)
.group(groupAlpha)
.on("filtered", function(chart) {
//do stuff
});
dc.pieChart(myDomId2)
.dimension(dimBeta)
.group(groupBeta)
.on("filtered", function(chart) {
//do stuff
});
into something like this...
var ndx = crossfilter(data);
var dimAlpha = ndx.dimension(function(d) {return d.alpha});
var dimBeta = ndx.dimension(function(d) {return d.beta});
var groupAlpha = dimAlpha.group().reduceSum(function(d) {return 1;});
var groupBeta = dimBeta.group().reduceSum(function(d) {return 1;});
dc.pieChart(myDomId1)
.dimension(dimAlpha)
.group(groupAlpha);
dc.pieChart(myDomId2)
.dimension(dimBeta)
.group(groupBeta);
ndx.on("filtered", function() {
//do stuff
})
If you've got a million charts and don't want to have to attach the event listener to each one manually, you could iterate through the chart registry and add them that way. Ex:
dc.chartRegistry.list().forEach(function(chart) {
chart.on('filtered', function() {
// your event listener code goes here.
});
});
Note that this code must go after the charts have instantiated to work.
In the absence of a way to attach the callback once globally, one thing you could do to mitigate the risk from duplicate code is to define the callback function once and pass in a reference instead of defining it inline on each chart.
function my_func() {
// do stuff
}
dc.pieChart(myDomId2)
.dimension(dimBeta)
.group(groupBeta)
.on("filtered", my_func);
chart and filter can also be passed to the filter function something like:
function my_func(chart,filter) {
// do stuff
}
dc.pieChart(myDomId2)
.dimension(dimBeta)
.group(groupBeta)
.on("filtered", my_func);

Is there a simple way in ASP.Net to get the current URL with some query parameters changed?

I've had several cases where I had a page with several query parameters - most recently a search results page - and needed to create a link to the same page with one or more query parameters changed in the URL. This seems like such a common use case that I feel as though there must be some simple built-in way of doing it.
Right now, I'm using a function I wrote which takes in a dictionary of parameters and values and merges them with the params and values from Request.QueryString. Parameters given with a null value are removed. It works, but I'm open to simpler methods.
Minor improvements I'd suggest:
//...
{
UriBuilder ub = new UriBuilder(Request.Url);
//...
ub.Query = string.Join("&", parameters.Select(kv => string.Format("{0}={1}", Server.UrlEncode(kv.Key), Server.UrlEncode(kv.Value))));
return ub.ToString();
}
Edit
Actually the return value should also be a Uri type but I didn't want to introduce any breaking changes.
The function I'm using now:
public string ThisPageWithParams(IDictionary<string, string> newParameters)
{
string url = Request.Url.AbsolutePath + "?";
var parameters = new Dictionary<string, string>();
foreach (string k in Request.QueryString)
{
parameters[k] = Request.QueryString[k];
}
foreach (var kv in newParameters)
{
if (newParameters[kv.Key] == null)
{
parameters.Remove(kv.Key);
}
else
{
parameters[kv.Key] = kv.Value;
}
}
url += string.Join("&", parameters.Select(kv => Server.UrlEncode(kv.Key) + "=" + Server.UrlEncode(kv.Value)));
return url;
}

Resources