I'm working on a form for user input, and one of the items (a multiple option select) has an inordinate amount of choices (~1600), so it's gotta get filtered down to be digestible. I've got 3 filter fields (dropdowns) that I'm requiring to have completed before I make an AJAX call back to the DB and get an updated list. It's similar to How to filter the options of a drop down list using another drop down list, however I also don't want to lose any items that were previously selected. Here's the signature for the function I've prototyped:
public JsonResult GetContentStandardsForUser(string type, string grade, string subject, List<SelectListItem> selected)
What I want is to return the new list of items (and not lose the ones that were already selected), and have the pick-list update.
What is this AJAX call going to look like (using jquery)? Should I just include the current selected values in my query, or can I pass the SelectListItems like I've written above?
After some thought about the fantasy football example I presented, I came up with a solution. I make two multi-selects, one of available, one of selected. Only the "selected" list gets bound to the model-- the available list is what gets updated as a result of the query.
If someone can come up with a single-select control solution, I'm still interested, but this is a good workaround for me, for now. The reason I was looking for a single-select solution was that I was already using this plugin (http://www.virtuosoft.eu/code/bootstrap-duallistbox/) to filter my selected/available lists.
ETA: I realized I can do this in a single listbox with jquery. Using the ID, loop through the options, if it's not selected, remove it. Then add all new options from the query. Voila!
ETA2: Now with code!
//Filter content standards
$("#csType, #csGrade, #csSubject").change(function(){
var type = $("#csType").val();
var grade = $("#csGrade").val();
var subject = $("#csSubject").val();
if(type != "" && grade != "" && subject != "")
{
$("#csList option:not(:selected)").remove();
var items="";
$.getJSON("#Url.Action("GetContentStandardsForUser","Summary")", {type:type, grade:grade, subject:subject} ,function (data) {
$.each(data,function(index,item){
items+="<option value='"+item.Value+"'>"+item.Text+"</option>"
});
$("#csList").append(items)
$("#csList").trigger('bootstrapduallistbox.refresh', true);
});
}
});
After binding the options, call following function.
$('#csList').multiselect('rebuild');
Related
I'm developing a personal frontend for my Media Server that entails the use of Entity Framework Core, and adding the Movies within my Media Server to a database. So far, i've got it working just as I want it to, where I can manually search a film, search TMDB using the API and save the film/studios in my db. What I want to do, however, is have an action called 'Scrape' that will, well, 'scrape' my media server for a list of movies, check if they exist in my db and if not, search these films on TMDB and save them automatically. I've also got this working...kind of.
For example, i'll have a List that will be looped through in the 'Scrape' controller, and this list is a list of movies that need to be searched, so:
Avengers: Infinity War
The Avengers
Tron
Harry Potter
I'm running the list through a foreach() loop, and for each item i'm going through the search procedure, and I can check how many results there are. Now this is where I run into my problem. If the length of the result is more than one, I need the user to be able to search through these results midloop, select a film then have the selected film be added. I'm able to cycle through my List and add all of the films that only have one result, but its the ones that have multiple. For example, 'Tron' is going to return more than one result, and the user needs to determine which version of Tron they wanted to add.
So this is the controller:
List<string> items = NetworkScrape.ScrapeFolders();
foreach (var item in items)
{
//Results from the movie search
SearchContainer<SearchMovie> Results = client.SearchMovieAsync(item).Result;
if (Results.Results.Count == 0)
{
Console.WriteLine(item + " could not be found.");
continue;
}
if (Results.Results.Count == 1)
{
Console.WriteLine(item + " only has one entry, auto add.");
MoviesSelectViewModel vm = new MoviesSelectViewModel
{
TMDBid = Results.Results[0].Id
};
//Add the movie to the DB
await Create(vm);
continue;
}
if (Results.Results.Count > 1)
{
Console.WriteLine(item + " has more than one entry, manual input required.");
//This is where the user would select the film
continue;
}
}
I've only got all of the WriteLine's for testing purposes, and 'items' is the list of movies to search. The final use case down the bottom, if results is more than 1, is where I want to pass 'Results.Results' to a View where the user is shown a table of the search results, in which they can select, but I don't know how to make the foreach loop wait for that result from the view, and even if i could halt the loop i don't exactly know how I can let the loop know when it is okay to 'continue'. I tried await but you can't do that with a View so i'm really lost.
Sorry for the big, long post but I just thought i'd give as much information as I can to help illustrate my problem because i'm totally lost. Any help at all would be appreciated, or even a better way of doing this.
I am working on a C# .NET application.
I have a webpage which features a search bar. When the User starts typing I use the Jquery Keyup function to automatically invoke a Webservice ( I am using a Controller call that extends ApiController).
The point of the Webservice is to return a list of data from the Database to the View, based on what the User has entered into the Search bar.
If the User types the Letter "A", then inside the Webservice function I will query the database for all the objects whose name begin with the Letter "A".
My question is how do I change my code into the correct JSON format so that it can be returned to the View. At the moment my query is returning IQueryable. The code below gets called fine by Ajax.
So, I believe that the problem in inside the Action method below. The parameter "term" is the letter that the User types into the search bar.
[System.Web.Http.HttpGet]
public JsonResult GetAllofTheProducts(string term)
{
//var JsonArray = Json.stringify(products);
List<string>vehicle;
vehicle = db.Vechicle.Where(v => v.CarName.Equals(term) || v.CarName.ToLower().Contains(term.ToLower()) || v.CarName.ToUpper().Contains(term.ToUpper()));
//var json = new JavaScriptSerializer().Serialize(result);
// return json;
return Json(vehicle);
}
Update:
To expand on my question, I want to know how to change the result of my database query to a string so that I can pass it to a View. As this is an Ajax request and I can't directly pass the DB result.
I'm not sure if you're getting an error out of this code, or if you're receiving anything client-side.
Assuming you have no error, and you're receiving an empty JSON Array, I think you should explicitly cast your result as a list with .ToList() to make sure you get your data from the database. (As long as you don't ask to get an item from vehicle, it doesn't get loaded)
vehicle = db.Vechicle.Where(v => v.CarName.ToLower().Contains(term.ToLower())).ToList();
Also I removed some not needed part of your query
Searching for an exact match will return less results than a partial match.
Putting everything on the same case is a good idea, as it eliminates all differences between user input and the dataset, but then you have to choose either lowercasing or uppercasing (As they will give you the same result)
EDIT 2 :
I cannot comment as I have too few reputation so here is the answer :
Add the following
vehicle = db.Vechicle.Where(v => v.CarName.ToLower().Contains(term.ToLower())).Select(v => v.<NAME>).ToList();
As you're returning a list of vehicle, you only want to get Name of the brand, just replace with the field name corresponding.
I am working on a small expense tracking program. The idea is to have a list that holds Expense objects that can be manipulated and used to perform calculations.
I was able to create the List without issue and populate it with several dummy expenses. My expenses are grouped by category, Expense.expenseType, to allow me to do calculations for analysis so I am trying to make another List that will store category names and relevant calculations values. The list of category names is meant to remove duplicates but so far I've been unsuccessful at populating it.
My approach for creating the List has been to define a Category class that holds only a string parameter for categoryName and a float for categoryTotal although the latter is initialized to 0.00. I then have a For loop that copies the names into the List and a second For loop that removes indexes based on the name once they've been alphabetized. I've tried different variations of this but ultimately I get either an index that is out of bounds or a reduced but still duplicates list of categoryName.
Really hoping to get some advice so I could move forward with the code. I didn't add the actual code since I'm new to C#/VS and figure I may be approaching the problem all wrong.
Edit 1: Based on the feedback I got, the function I am using is below:
public void getCategories(List<Category> passedCategories)
{
passedCategories = passedCategories.GroupBy(Category =>Category.strName)
.Select(gr => new Category
{
strName = gr.Key,
fltTotal = gr.Sum(ex => ex.Value)
});
}
This function is not working, I have a few points I wanted to clarify and I am sure there are others I missed.
Passed categories is a List of Categories that have three parameters - strName, fltTotal and fltPercent. The latter two are currently set to zero when the whole list is populated via a temp Category. The strName is being copied from an Expense List with many more parameters. Since the Category name will repeat in the Expense List, I am trying to remove all duplicates so I can have just the different categories. I took out var since I am passing the List in, should I not have done this? What am I missing?
Thanks again for the help,
Yusif Nurizade
That you need is something like the following. I say something, because I don't see your code and I have to imagine it. For instance, I don't know the name of the property for the amount of expense. I assumed that this is called Value.
// This would be the list of expenses. You have to populate it with data.
var expenses = new List<Expense>();
// Using LINQ you can achieve that you want in a few lines.
// First you group by your data by their categories.
// Then you calculate the total expense for each category.
var statistics = expenses.GroupBy(expense=>expsense.Type)
.Select(gr=> new Category
{
Name = gr.Key,
Total = gr.Sum(ex=>ex.Value)
});
1-problem: I need to enable users to select one or more things from a large amount of information that is grouped into a hierarchical structure for selection, data entry, were data could have a depth of 4, 5 parent categories.
2-functionality I´m looking for:
Similar to eBay shows cascading lists when selecting an item’s category. When the page is displayed, you only get the first list box. After selecting one in the first, the second is displayed. The process continues until the selected category does not have sub-categories.
}
3-actual table and query:
table:
-int Id
-string Name
-int ParentId
query:
public IList<CategoryTable> listcategories(int parentId)
{
var query = from c in categorytable
where c.ParentId == parentId
select c;
var result= query.ToList();
return result;
}
4-I dont know how to start, any guideline, live example jsfiddle, demo or tutorial would be greatly appreciated.
brgds
UPDATE: I believe that this functionality is not very developed in webtutorials and questions. consequently I started a bounty for a great answer. I will asign the bounty for a live example of the functionality previous commented. thanks!
What I have learned by handling large amounts of data is:
don't try to load all data at once to the client
load only the data the client actually needs
do the filtering, searching and sorting in the database, e.g. by stored procedures. Especially for data, which are distributed across multiple tables.
optimize your database queries, indexes are good
keep always in mind how many simultanious queries do you expect
linq is good but not for everything when handling large data
spend time to think and plan what data are really needed
To display the data on your webpage there many jQuery plugins to list data where you could bind functions to an "selected"-event. For example knockOut.js, which comes with MVC4. You may don't need a fully loaded jQuery "hierachical-data-list-display"-plugin. Perhaps you can realize it by using "seleted"-events, ajax loading and show/hide functions.
According to your comments I would think of a combination of jQuery and MVC:
in MVC I would create a patial view like
#model MvcApplication.Models.DataModel
<ol id="#Model.DataCategorieLevel">
#for (var i = 0; Model.Data.Count > i; i++)
{
<li value="#Model.Data[i].ItemId" onclick="itemSelected(#Model.Data[i].ItemId, #Model.DataCategoryLevel);" >#Model.Data[i].ItemName</li>
}
</ol>
the javascript could be something like:
function itemSelected(selectedItemId, itemCategoryLevel) {
// ajax call to an action which loads the next categorie items into the partial view and returns them
// on success remove all lists with an category - level lower than itemCategoryLevel
// append the returned List to the HTML-container which holds the lists
}
in the called MVC-Action I would determine if it is the last category level or not. If it is the last level, I would return a different partial view with other onclick event bindings
This is what I would try to realize, before I start searching for some plugins
I'm using knockout and Webapi to power cascading dropdowns in an app I'm developing at the moment.
View
I've got a basic dropdown list like below.
<select data-bind="options: CurrentList,
optionsText: 'name',
value: CurrentListSelectedItem,
optionsCaption: 'Please Select...'"></select>
View Model
self.CurrentList = ko.observableArray(CurrentListData);
self.CurrentListSelectedItem = ko.observable();
self.CurrentListSelectedItem.subscribe(function () {
//ajaxcall to populate list 2
});
Server side I've got a simple rest service that take an Id of a point in the tree and returns all its children, this way you can just chain as many of these dropdowns together as you wish (as long as your hierarchy has the levels to match.
See fiddle of working example with mocked data http://jsfiddle.net/tgriley1/vEBGS/
I recently had a similar problem when using Cascading Drop-downs and I did something like this.
Firstly, write some jquery on the view so that when you select the first item it sends an ajax request to the server, and brings back a JSON or xml response.
I did something like
<script>
$(function () {
$("select#ParentId").change(function (evt) {
$.ajax({
url: "/Home/GetChildItems",
type: 'Post',
data: { ParentId: $("select#ParentId").val() },
success: function (data) {
var items = "";
$.each(data, function (i, val) {
items += "<option value='" + val.ChildId + "'>" + val.ChildName + "</option>";
});
$("select#ChildDropDown").empty().html(items);
}
});
});
});
</script>
On the Controller, something like
Public JsonResult GetChildItems(int ParentId)
{
//code to retrieve the data
JsonResult result = new JsonResult();
result.Data = **object that contains the child data**;
return result;
}
I'm a beginner myself, so I'm not sure how good this code is, but it worked for me when creating cascading drop-downs using jquery.
Hope it helps.
Link to the cascading drop down question : Populating dropdown with JSON result - Cascading DropDown using MVC3, JQuery, Ajax, JSON
Hi I had the same scenario , What I used is, a autocomplete list with with web API, after specific number of characters , it calls the Web API and loads the data for the particular wild card.
Apart from this when I found that data returned is still large , I added pagination at SQL server end
The telerik demo is always a good place to learn MVC from
http://demos.telerik.com/aspnet-mvc/razor/combobox/cascadingcombobox
This does not exactly use listboxes as per your screenshots but it could very easily be changed to use them. With a few javascript modifications you could have unlimited levels.
Here is another one:
http://weblogs.asp.net/raduenuca/archive/2011/04/03/asp-net-mvc-cascading-dropdown-lists-tutorial-part-5-1-cascading-using-jquery-ajax-ajax-and-dom-objects.aspx
I have a few generic questions about what are the best practices for SharePoint(2010).
I am currently implementing a feature that requires me to fetch information from a list. I am not quite sure on how to manage these information. I created a class that helps me manage theses information (User.cs). I have a getter in the class that currently searches for a value in a specific list. How should i handle the value ? Should i keep it in a member and refresh only when its subject to changes or should i refresh the value from the list each time i get it ?
private void doesUserHasActivities(){
using(SPSite site = new SPSite("http://vmsharepoint2010/")){
using(SPWeb web = site.openWeb("http://vmsharepoint2010/")){
SPList list = web.list["Users"];
SPListItem user;
/*Information values is refresh each time its accessed, is this bad ?*/
for(int i=0; i < list.items.length; i++){
user = list.item[i];
string accName = user["Acc_Name"];
if(accName == this.providedAccountname){//providedAccountname from a TextBox
//found the user i wanted into the list
//look if the list has data
bool hasActivities = user["Activities"] != null;
}
}
}
}
}
Also, is there other ways to access specific data, in this case the activities list without looping through each rows trying to match the correct user and then looking up the values in the activities list ?
Can i store the row itself as a member for my meta data ? Will my reference still point to the row of the user list i want to if another user is added ?
You'll need to learn CAML and perform a CAML query.
Create an SPQuery object. Set it's Query property to be what you need it to be, then use list.getItems(SPQuery query) to get just the items that match your query.
You can figure out the CAML for it yourself; you'll need to learn it if you want to deal with SharePoint code at all. There is lots of information on basic syntax, and tools for helping auto-generate it based on more user friendly syntax.
The items won't update dynamically when items are added to the list or updated in the list; you will need to re-run the query.