I am building a meteor based webapp. One of the pages has a drop down menu, which the user has to select options (various school districts) from. The selection needs to be detected, followed by querying the database filtering documents based on the selection and counting the documents returned, followed by rendering a template (a chart built using highcharts.js)
Code as follows:
Template.districtDropdown.events({
'change' : function(event, template){
event.preventDefault();
var selectedValue = template.$("#selectDistrict").val();
console.log("You Selected " + selectedValue);
var filter = {
find: {
'School District' : selectedValue
}
};
Meteor.subscribe('aggByDistrict', filter);
productNames2 = _.uniq(CombinedData.find().map( function(doc) { return doc.Product; }));
console.log(productNames2);
var productValues2 = [];
for(var i = 0; i < productNames2.length; i++) {
productValues2.push(CombinedData.find({'Product' : productNames2[i]}).count())
};
console.log(productValues2);
}
});
I'm facing three issues.
The console on the client side throws an error "productNames2" has not been defined as soon as the page loads, pointing to the line which has the for loop (even before I've made any selection).
The first time I click on one of the options in the drop down menu, I get empty arrays (the two console.log(productNames2) and console.log(productValues2), but when I click on some other option, it works the second time. No idea why.
I want to render a template {{> highchart2}} after the user has selected an option from the drop down and the two arrays (productNames2, productValues2) have been populated.
Can anyone give me ideas on how I can go about resolving these issues?
Several problems with your code
Subscribe needs to be put in Template.districtDropdown.created. If you subscribe during the events, there might be the postpone during the subscription and no data available during the events
event should be attached to a DOM component. As in change #selectDistrict and then, you select the value like this var selectedValue = $(event.target).val();
Related
I'm loading multiple partial views into the same cshtml page. All goes well until they need to use the scripts. As i'm using code like
var grid = $("#grid").data("kendoGrid");
var selected = grid.selected();
This code works fine with one grid, but starts showing issues when multiple grids are in place. The problem is that "#grid" is a reference to the name of the kendo grid. Is there a way to make this dynamic so it can be used by multiple grids?
I think the same problem would occur when there are multiple grids in the same page as it can't distinct what grid to refer to. Giving the grids different id's would work, but then the code in the script will return an undefined error on grid.selected().
Update:
So the solution of using
var grid = $(".k-grid").data("kendoGrid");
works to a certain point. It loads the data into the grid, but fails to do anything else. For example a part of my code for enabling an update and delete button doesn't work on the 2nd and 3rd partial view.
var grid = $(".k-grid").data("kendoGrid");
var selected = grid.select();
if (selected.length > 0) {
$("#btnCopy,#btnEdit,#btnDelete").removeClass("k-state-disabled");
} else {
$("#btnCopy,#btnEdit,#btnDelete").addClass("k-state-disabled");
}
Somehow the code only starts working for grid 2 and 3 after i have selected a row on grid 1, which is not as intended.
Instead of id(#Grid) you can use class(.k-grid):
var grid = $(".k-grid").data("kendoGrid");
The solution I found with help of a senior programmer is to save the grid data into a global variable like this.
var PartialGridData = PartialGridData || {};
After that I'm setting and changing the variable whenever changing the partial view.
PartialGridData.selectedGrid = $("#PartialGrid1").data("kendoGrid");
Where the name #PartialGrid1 is the name of the current grid.
This means I need to write this code as many times as I have grids, but it also fixes a lot of problems. After that I use it to select the correct data.
var grid = PartialGridData.selectedGrid;
var selected = grid.select();
if (selected.length > 0) {
$("#btnCopy,#btnEdit,#btnDelete").removeClass("k-state-disabled");
} else {
$("#btnCopy,#btnEdit,#btnDelete").addClass("k-state-disabled");
}
Another option would be to use e.sender.
function onRowSelect(e) {
var grid = e.sender;
var selected = grid.select();
if (selected.length > 0) {
$("#btnCopy,#btnEdit,#btnDelete").removeClass("k-state-disabled");
} else {
$("#btnCopy,#btnEdit,#btnDelete").addClass("k-state-disabled");
}
}
Both solutions have their drawbacks though. Not all methods get the variable e used for e.sender and changing partial views in a way that is not caught will cause the global variable not to be updated, so this has to be kept in check.
The Task
Picture the typical search-bar and list of results. With framework7 in my Cordova app we can of course implement this easily even with a virtual list where elements aren't all being rendered. But what I'm trying to implement is a search-bar which will effect two virtual lists. The reason for this is as part of the app I'm creating there will be a list for new and refurbished equipment. Each list is on a different slider tab on the same page, so only one list will be seen at any one moment. But I need to use a singular search-bar to filter both.
What I've done so far
Currently the slider with two separate virtual lists is set up, the search bar is initiated. Is there any good way to allow the searchbar to apply to both lists without going crazy with the customSearch true parameter. If that is the only option how would I keep the default methods for filtering lists, I simply want to apply it twice.
I've also considered creating a second searchbar with display:none and having it copy input over from the seen searchbar. Then hidden searchbar could apply to one list while the seen one would apply to the other. But that would be really hacky and not neat at all.
Sorry If this is a bit unclear, I'm not sure how best to approach the challenge, thanks for any help
I initialise my two virtual lists, I make the search function accessable from outside of that. Then I initalise my searchbar with customSearch true, on search I use my virtual list (vl) array and search them individually using the filter and query functions available. It was a bit of a pain but this works perfectly fine. The vl[1] in this example is just a copy of vl[0] since I haven't actually set it up yet.
function virtualSearchAll(query,items){//search query
var foundItems = [];
for (var i = 0; i < items.length; i++) {
// Check if title contains query string
if (items[i].internal_descriptn.toLowerCase().indexOf(query.toLowerCase().trim()) >= 0) foundItems.push(i);
}
// Return array with indexes of matched items
return foundItems;
}
var vl = [];
vl[0] = myApp.virtualList('.vl0', {//initialise new products
items: selectProd,
template: '<li data-value="{{model_id}}" class="item-content"><div class="item-inner"><div class="item-title list-title">{{internal_descriptn}}</div></div></li>',
searchAll: function(query,items) {
return virtualSearchAll(query, items);
}
});
vl[1] = myApp.virtualList('.vl1', {//initialise test/referb products
items: [{internal_descriptn:"test desc",model_id:"wehayy"}],
template: '<li data-value="{{model_id}}" class="item-content"><div class="item-inner"><div class="item-title list-title">{{internal_descriptn}}</div></div></li>',
searchAll: function(query,items) {
return virtualSearchAll(query, items);
}
});
var mySearchbar = myApp.searchbar('.searchbar', {
customSearch: true,
searchIn: '.item-title',
onSearch: function(s) {
previousQuery = s.query;
for (let n in vl) {
let vlItems = virtualSearchAll(s.query,vl[n].items);
vl[n].filterItems(vlItems);
if(vlItems.length === 0) {//if the search has no results then show no results element else hide it
$('.vl'+n+'-not-found').show();
} else {
$('.vl'+n+'-not-found').hide();
}
}
highlightRows();
}
});
I should add that highlightRows() is part of a different functionality which needs to be refreshed on every search. You can ignore that
Here is a drop down list in SmartClient: http://www.smartclient.com/#dropdownGrid.
I want to make a selection using JavaScript. Like, I run some JavaScript in console, and the drop list will select a specific item.
I did some research, found a code snap to do this (the code is in Java, but I think there should be similar functions in JavaScript):
Record rec = perdomainGrid.getRecordList().find("domaine_id", domaine_id);
perdomainGrid.selectSingleRecord(rec);
If I want to make selection, first I need to obtain perdomainGrid object. In my above giving link, the drop down list id in GWT is exampleForm (can be seen in dropDownGrid.js tab). I try to get the object by:
var form = isc.DynamicForm.getById("exampleForm");
form does exist, but there is no getRecordList() function on it, there is selectSingleRecord() function on it though.
I try to check form's class by form.className, its value is normal. I don't know what does that mean.
I'm kind of confused now. Could somebody help me on this?
isc_SelectItem_5 has a function called pickValue(), it takes one parameter SKU. This function can be used to select item.
var itemName = "Letter Tray Front Load Tenex 200 Class Blk #23001";
var data = isc_SelectItem_5.optionDataSource.cacheData;
var targetSKU = data.find(function(e) {
if (e.itemName == itemName) {
return e;
}
}).SKU;
isc_SelectItem_5.pickValue(targetSKU);
I have a filter_horizontal selector in my Django admin that has a list of categories for products (this is on a product page in the admin). I want to change how the product change form looks based on the category or categories that are chosen in the filter_horizontal box.
I want to call a function every time a category is moved from the from or to section of the filter_horizontal.
What I have now is:
(function($){
$(document).ready(function(){
function toggleAttributeSection(choices) {
$.getJSON('/ajax/category-type/', { id: choices}, function (data, jqXHR) {
// check the data and make changes according to the choices
});
}
// The id in the assignment below is correct, but maybe I need to add option[]??
var $category = $('#id_category_to');
$category.change(function(){
toggleAttributeSection($(this).val());
});
});
})(django.jQuery);
The function never gets called when I move categories from the left side to the right side, or vice versa, of the filter_horizontal.
I assume that $category.change() is not correct, but I don't know what other events might be triggered when the filter_horizontal is changed. Also, I know there are multiple options inside of the select box. I haven't gotten that far yet, but how do I ensure all of them are passed to the function?
If anyone can point me in the right direction I would be very grateful. Thank!
You need to extend the SelectBox.redisplay function in a scope like so:
(function() {
var oldRedisplay = SelectBox.redisplay;
SelectBox.redisplay = function(id) {
oldRedisplay.call(this, id);
// do something
};
})();
Make sure to apply this after SelectBox has been initialized on the page and every time a select box refreshes (option moves, filter is added, etc.) your new function will be called.
(Code courtesy of Cork on #jquery)
I finally figured this out. Here is how it is done if anyone stumbles on this question. You need to listen for change events on both the _from and _to fields in the Django filter_horizontal and use a timeout to allow the Django javascript to finish running before you pull the contents of the _from or _to fields. Here is the code that worked for me:
var $category = $('#id_category_to');
$category.change(function(){
setTimeout(function () { toggleAttributeSection(getFilterCategoryIds()) }, 500);
});
var $avail_category = $('#id_category_from');
$avail_category.change(function(){
setTimeout(function () { toggleAttributeSection(getFilterCategoryIds()) }, 500);
});
And this is how I get the contents of the _to field:
function getFilterCategoryIds() {
var x = document.getElementById("id_category_to");
var counti;
var ids = [];
for (counti = 0; counti < x.length; counti++) {
ids.push(x.options[counti].value);
}
return ids;
}
I know it was a convoluted question and answer and people won't come across this often but hopefully it helps someone out.
I am working on a phonegap project, In which I have a dynamic list of countries coming from backend. Ex. USA, Canada, India. I have to display USA as a default selected value which is working fine. Now the problem is - when I select Canada from drop-down box and if I exit(force close from setting) the value gets stored on Local storage/DB but it doesn't display as a selected value in drop-down window.
I searched for displaying dynamic value stored in DB and display in drop-down.
Kindly help. Thanks in advance.
Here is my Code :
if(window.localStorage.getItem("my_country") == '' || window.localStorage.getItem("my_country")== null )
{
window.localStorage.setItem("my_country",'US');
window.localStorage.setItem("my_country_name",'USA');
var ccode = window.localStorage.getItem("my_country");
}
else
{
var ccode = window.localStorage.getItem("my_country"); //previously selected country
}
jQuery.each(result.d.listCountrys, function(key,value)
{
if(ccode==value.CountryCode) //to get the previously stored value and that will become selected in drdwn.
{
jQuery("#drpDoctorSearchCountry").append("<option class='ccmp' value='"+value.CountryCode+"' Selected>" + value.strCountryName+ "</option>");
jQuery("#drpBillingCountry").append("<option class='ccmp' value='"+value.CountryCode+"' Selected>" + value.strCountryName+ "</option>");
}
else
{
jQuery("#drpDoctorSearchCountry").append("<option class='ccmp' value='"+value.CountryCode+"'>" + value.strCountryName+ "</option>");
jQuery("#drpBillingCountry").append("<option class='ccmp' value='"+value.CountryCode+"'>" + value.strCountryName+ "</option>");
}
});
Edit:
I started writing this answer before the question was edited. Variable names won't match up. But one should get the idea.
Assumption:
When a user selects (perhaps clicks on) an option (in a select field), it's value is stored in localStorage. Say under localStorage.cPref.
If the user has (previously) selected such a value, it should appear as the default (first) value in a drop-down.
Solution:
Before displaying the options, you should check the user's country preference is already in localStorage.
If so, move that country to the beginning of the list (of countries.)
If not so, it'd mean that the user hasn't yet chosen any option, and there no changes need to be made.
Instead of hard-coding the country options in HTML, it'd be best to use a javascript function which accepts a list (array) of countries.
Manipulating this list and then writing the options to HTML would be better than correcting options after they've already been rendered ( if the need be for such correction.)
Code:
function renderOptions (cList) { // cList is an array of countries.
var i, selectNode, optionNode;
if (localStorage.cPref) { // cPref stores the (previously) selected country.
i = cList.indexOf(localStorage.cPref);
if (i > -1) {
cList = [cList[i]].concat(cList.slice(0, i)).concat(cList.slice(i+1));
// Moving cPref to the front of cList.
}
}
selectNode = document.createElement('select');
for (i = 0; i < cList.length; i += 1) {
optionNode = document.createElement('option');
optionNode.value = cList[i];
optionNode.innerHTML = cList[i];
selectNode.appendChild(optionNode);
}
document.body.appendChild(selectNode);
// you'd perhaps want to use insertBefore(..) instead.
return;
}
renderOptions(['USA', 'Canada', 'India', 'Mexico'])
// The function call may be hard-coded in HTML or produced by a script (say python.)
And that's it! Hurray...
Gotcha:
If the client disables javascript he'd not even be able see the select field! Make sure you hard code the select options inside a <noscript> tag.
Hope I helped. :)