Dojo combo box specify label and value - javascript

I am trying to follow this example on how to setup a combo-box using dojo, but wondering how one can specify name and value programmatically. The example presented uses the same values for label and value - which is probably not one wants in most cases.
{
"identifier": "abbreviation",
"label": "name",
"items": [
{ "abbreviation": "AL", "name": "Alabama" },
... other 48 states here ...
{ "abbreviation": "WY", "name": "Wyoming" }
]
}

If you are asking how to replace the hard coded list in the example then here is what you have to do. In the above scenario items was used to specify the data which is an array (abbreviations and names) of values.
In your case you will need to get the data / object from your data source. Once you have that data/object expose it to the view. Once this has been done you can now do the following structure.
You store is really your items above however stateStore will be a java script array which contains the data from your data source.
stateStore = [{"abbreviation": "AL", "name": "Alabama"},
... other 48 states here ...,
{ "abbreviation": "WY", "name": "Wyoming" }]
// create FilteringSelect widget, populating its options from the store
var select = new dijit.form.FilteringSelect({
name: "stateSelect",
placeHolder: "Select a State",
store: stateStore
}, "stateSelect");
HTML
<div style="width:50%;float: left;">
<h1>dijit.form.Select</h1>
<label for="stateSelect">State:</label>
<div id="stateSelect"></div>
</div>

Related

Triggering an event from a custom formatter

I want to generate a table from a JSON objects array. Each object represents an application and has 4 properties: name, package, versions, and users.
name and package are textual, and users is numeric. versions, however, is an array of arrays: each internal array contains a version name and a version code. Here is a sample JSON:
[{
"name": "Angry Birds",
"package": "oldgames",
"versions": [
["alpha", 0.1],
["beta", 0.2],
["release", 1]
],
"users": 800
},
{
"name": "Temple Run",
"package": "oldgames",
"versions": [
["beta", 0.7],
["release", 2]
],
"users": 130
},
{
"name": "Snake",
"package": "veryoldgames",
"versions": [
["release", 0]
],
"users": 2
}]
The table requirements are as follows:
There should be 4 columns corresponding to the mentioned properties: Name, Package, Version (singular), and Users.
The Version column should contain a dropdown (an HTML select), with each option referring to a specific version. In addition, each dropdown contains an "All" option to refer to all the versions of the app.
The text of each option is the version name, and the value is the version code.
When a specific version is selected, an external function is called and returns the number of users that uses this specific version. Then, the row's Users cell is updated with the new number.
(I know it's a bit convoluted, and that there are probably better ways to visualize the data, but right now this is the architecture I have to implement and I can't change it)
To create the dropdown, I tried using the built-in List editor. I soon found out this is the wrong approach since the List editor is constructed with predefined values - identical values ​​for each and every row in the table, while I need every row to have a unique dropdown.
After researching a bit, I realized I needed to use a Custom Formatter. I take the versions array and manually construct a select. Here is a demo:
const data = [
{
"name": "Angry Birds",
"package": "oldgames",
"versions": [["alpha", 0.1], ["beta", 0.2], ["release", 1]],
"users": 800
},
{
"name": "Temple Run",
"package": "oldgames",
"versions": [["beta", 0.7], ["release", 2]],
"users": 130
},
{
"name": "Snake",
"package": "veryoldgames",
"versions": [["release", 0]],
"users": 2
}
];
new Tabulator("#example-table", {
data: data,
layout: "fitColumns",
height: 107,
columns: [
{
title: "Name",
field: "name",
},
{
title: "Package",
field: "package"
},
{
title: "Versions",
field: "versions",
formatter: function (cell, formatterParams, onRendered) {
const select = document.createElement("select");
const options = select.options;
options.add(new Option("all", "all"));
const value = cell.getValue();
for (let i = 0; i < value.length; i++) {
options.add(new Option(value[i][0], value[i][1]));
}
return select;
}
},
{
title: "Users",
field: "users"
}
],
});
<script src="https://unpkg.com/tabulator-tables/dist/js/tabulator.min.js"></script>
<link href="https://unpkg.com/tabulator-tables/dist/css/tabulator.min.css" rel="stylesheet"/>
<div id="example-table"></div>
The data is displayed properly. Initially, I planned to bind a change event listener to the select, but the documentation recommends not doing that:
...it is a bad idea to try to use code outside of Tabulator to
directly alter or bind events to DOM elements inside the table,
because there is a good chance that the element you are trying to
manipulate will be destroyed on the next scroll.
Instead, the documentation recommends using its predefined events:
Tabulator has a wide range of callbacks, formatters and other
functions that allow you to manipulate the table contents in a way
that is safe and won't be affected by the rows being recreated.
The closest event I could find is cellEditing. However, I don't know how to trigger it when the value of the select changes.
What is the recommended way to implement these requirements?

dependent dropdownlist with json and python

So I am making a dialog panel for my chat bot in django framework. The Dialog panel consists of intent and entities dropdown list and a dialog textarea. The dropdown list will be dependent on my training data which is in json format.
I want the dropdownlist so that if I choose intent, the entities dropdown list create itself automatically and show all the entities related to selected intent.
I have tried and I am able to show intent dropdown but that too had duplicate intents(which i removed using python set function).But I am unable to figure out how to show all entities based on one particular intent.
Help me. Here's my example json:
{"rasa_nlu_data": {
"common_examples": [
{
"text": "hey",
"intent": "greet",
"entities": []
},
{
"text": "yep",
"intent": "affirm",
"entities": []
},
{
"text": "i'm looking for a place to eat",
"intent": "restaurant_search",
"entities": []
},
{
"text": "i'm looking for a place in the north of town",
"intent": "restaurant_search",
"entities": [
{
"start": 31,
"end": 36,
"value": "north",
"entity": "location"
}
]
},
{
"text": "show me chinese restaurants",
"intent": "restaurant_search",
"entities": [
{
"start": 8,
"end": 15,
"value": "chinese",
"entity": "cuisine"
}
]
},
{
"text": "bye",
"intent": "goodbye",
"entities": []
}
]}}
Basically, all you have to do is loop over the items inside common_examples and check if the intent matches the selected value in the dropdown. If it does, add the entities to entities dropdown.
Since you haven't provided much info about your HTML, I'll try to answer with a few assumptions:
You've a select element with id intentDropdown to show intents.
You've a select element with id entitiesDropdown to show entities.
You're using jQuery.
The code contains some comments to explain what it does.
<!-- intents dropdown -->
<select id="intentsDrowpdown">
<!-- intent options-->
</select>
<!-- entities dropdown -->
<select id="entitesDrowpdown"></select>
<!-- Javascript -->
<script>
var data = {"rasa_nlu_data": { ... }}; // the json data
var totalExamples = data.rasa_nlu_data.common_examples.length; // total items inside common_examples
// listen to the event when selected value in
// the intent dropdown changes
$("#intentsDropdown").on('change', function() {
$("#entitiesDropdown").empty(); // clear the previously added entities from entities drowpdown
var selectedIntent = this.value; // currently selected intent
// loop over the items in common_examples
for (var i = 0; i < totalExamples; i++) {
var currentExample = data.rasa_nlu_data.common_examples[i] // current example in the loop
// see if the selected intent matches the
// intent of the current example in the loop
if (currentExample.intent == selectedIntent) {
// if intent matches
// loop over the items inside entities
// of the current example
for (var j = 0; j < currentExample.entities.length; j++) {
// add the option in the dropdown
$("#entitiesDropdown").append($('<option>', {
value: currentExample.entities[j].value,
text: currentExample.entities[j].entity
}));
}
}
}
});
</script>
Finally, I'd like to bring one thing to your notice. Conside the example below:
"entities": [
{
"start": 8,
"end": 15,
"value": "chinese",
"entity": "cuisine"
}
The entities list has one item in it. And that item has 4 sub-items in it. In your question, you haven't made it clear if you want to show all the sub-items in one dropdown option (e.g. start: 8, end: 15, value: chinese, entity: cuisine) or if you want a separate option for each sub-item.
The JS code that I've posted will create a dropdown option like this:
<option value="chinese">cuisine</option>.
If you want to display other items, you can just create another loop and keep adding the items to dropdown.

How can I create divs with conditional selects in angular 2?

Here is my html component:
<div *ngFor="let chart of barChartTypeSelect">
{{chart.mainChart}}
<select [(ngModel)]="selectedRepositoryName" (ngModelChange)="onRepositorySelected()">
<option *ngFor=" let repository of barChartTypeSelect" [value]="repository.mainChart">
{{repository.mainChart}}
</option>
</select>
</div>
In my typescript file, I defined the following:
private onRepositorySelected() {
this.selectedRepository = this.barChartTypeSelect.find(repository => repository.mainChart === this.selectedRepositoryName);
}
What I am trying to achieve is to create dynamic divs based on a json file that I parsed. Each div contains a chart with a conditional selects to adjust it. By parsing the json file and being aware of each object, we can actually decide if we need to attach a selects or not (if the object only contains a key but without any value, then there is no selects).
In other words, the json object maps for each key on the first level to a chart. Every secondary level is a select option that redraws the chart on select, every third level is also a select option that only gets displayed if the second select is checked, and so on.
Here is the object parsed:
{
"consumerPriceIndex": [],
"grossDomesticProductPercentage": [],
"inflationRate": [],
"newUnderCons": [
"apartment",
"building",
"villa"
],
"population": [
"quarter",
"year"
],
"populationChange": [
"quarter",
"year"
],
"transactionVolume": {
"apartment": [
"quarter",
"year"
],
"total": [
"quarter",
"year"
],
"villa": [
"quarter",
"year"
]
},
"transactionVolumeOilIndex_total_quarter": []
}
I can always hard code the values, but I want to achieve the mvc structure as closely as possible. Thank you.

How can I index child object properties in an array using ydn-db-fulltext?

I'm using Ydn-Db-Fulltext to allow users to search a local database of contacts in an HTML5 app. So far, when it comes to searching for names of people, it works great, is smart, and returns results instantly.
Here's an example of a contact object that contains an array of contact Methods:
{
"source": "COMPANY",
"ownerPin": "12345",
"name": "brian wilkins",
"dateUpdated": "2014-03-18T14:41:05.217Z",
"dateAdded": "2014-03-18T14:41:05.217Z",
"isFavorite": false,
"socialId": "54321",
"id": "1",
"deleted": false,
"edited": false,
"favorite": false,
"contactMethods": [
{
"id": "4321",
"contactKey": "12321",
"contactId": "1",
"value": "brian.wilkins#geemail.com",
"kind": "email",
"ownerPin": "12345",
"isPrimary": false
},
{
"id": "5432",
"contactKey": "2",
"contactId": "1",
"kind": "phone",
"ownerPin": "12345",
"isPrimary": false
},
{
"id": "23",
"contactKey": "333",
"contactId": "1",
"value": "112345",
"kind": "extension",
"ownerPin": "12345",
"isPrimary": false
}
]
}
To create the index on the "name" property, I setup the fullTextCatalog as follows:
fullTextCatalogs: [{
name: 'name',
lang: 'en',
sources: [
{
storeName: 'contacts',
keyPath: 'id',
weight: 1.0
}, {
storeName: 'contacts',
keyPath: 'name',
weight: 0.5
}
]
}],
stores: [
{
name: 'contacts',
keyPath: 'id',
autoIncrement: true
}
]
};
this.db = new ydn.db.Storage('thedatabase', db_schema);
I can search by name or by id (the key) and get a list of contacts that match. Little appears to be stored in memory. Every search queries the local backing indexedDB database.
The challenge is that I also want to be able to search based on email address and extension, which are stored in the contactMethods property inside an array of contactMethods. The "value" property is where we store the email address and/or extension depending on the contactMethod type.
I tried adding contactMethods as a secondary searchable object store, but this resulted in searches for "Brian" returning two results, both the contact containing the name, and the contactMethod containing the email address. Ideally, I'd want to take the contactId (foreign key to the contact) and use it to pull the actual contact object, but it seems like this could create very expensive overhead and negate the benefits of this great search tool.
Is there a way to index object properties that are not at the parent level? How can I approach this in a way that would scale and not eat up all of the resources?
this.db.get(entry.storeName, entry.primaryKey).done(function(x) {
this.textContent += ' [Full name: ' + x.name + ']'; // this is in the contact
this.textContent += ' [email: ' + x.value + ']'; // but this is in the contactMethod
}, span);
Is there a way to index object properties that are not at the parent level?
keyPath can refer to deep object property by using dotted notation. For example, you could specify contactMethods.value to index email, but unfortunately it does not work with array value - as in this case.
So, obvious choice is keeping contactMethods record in separate object store using parent-child relationship. Since ydn-db currently does not support embedded attribute in the schema, you will have to load all child records when loading parent object.
Alternatively, IndexedDB v2 may have virtual index generated by a function expression. You can use in ydn-db by generator in index schema, for example:
stores: [
{
name: 'contacts',
keyPath: 'id',
autoIncrement: true,
indexes: [{
name: '$emails',
multiEntry: true,
generator: function(record) {
return record.contactMethods.map(function(x) {return x.value};
})
}]
}
]
One thing to note though, the generated field $emails will appear when you load the data. It likely will be removed from the record so as to match with v2 spec.
We are using this generator index heavily in multiple projects, so I will fix bug.
Indexing id and email address in full text search is convenient, but does not make sense because phonetic base full text search will be index them as it is without normalization.

Backbone? Can.js? Ghetto DIY? How should I work with this data?

I'm working on an application that lets our security dispatchers update a page that contains current road and campus conditions. The backend is a nodejs/express stack with and the data is a simple JSON structure that looks something like this:
{
"campus": {"condition": "open", "status": "normal"},
"roads": {"condition": "wet", "status": "alert"},
"adjacentroads": {"condition": "not applicable", "status": "warning"},
"transit": {"condition": "on schedule", "status": "normal"},
"classes": {"condition": "on schedule", "status": "normal"},
"exams": {"condition": "on schedule", "status": "normal"},
"announcements" : "The campus is currently under attack by a herd of wild velociraptors. It is recommended that you do not come to campus at this time. Busses are delayed.",
"sidebar": [
"<p>Constant traffic updates can be heard on radio station AM1234. Traffic updates also run every 10 minutes on AM5678 and AM901.</p>",
"<p>This report is also available at <strong>555-555-1234</strong> and will be updated whenever conditions change.</p>"
],
"links": [
{
"category": "Transportation Links",
"links": [
{
"url": "http://www.localtransit.whatever",
"text" : "Local Transit Agency"
},
{
"url": "http://m.localtransit.whatever",
"text" : "Local Transit Agency Mobile Site"
}
]
},
{
"category": "Weather Forecasts",
"links": [
{
"url": "http://weatheroffice.ec.gc.ca/canada_e.",
"text" : "Environment Canada"
},
{
"url": "http://www.theweathernetwork.com",
"text" : "The Weather Network"
}
]
},
{
"category": "Campus Notices & Conditions",
"links": [
{
"url": "http://www.foo.bar/security",
"text" : "Security Alerts & Traffic Notices"
},
{
"url": "http://foo.bar/athletics/whatever",
"text" : "Recreation & Athletics Conditions"
}
]
},
{
"category": "Wildlife Links",
"links": [
{
"url": "http://velociraptors.info",
"text" : "Velociraptor Encounters"
}
]
}
],
"lastupdated": 1333151930179
}
I'm wondering what the best way of working with this data on the client side would be (e.g. on the page that the dispatchers use to update the data). The page is a mix of selects (the campus, roads, etc conditions), TinyMCE textareas (announcements and sidebar) and text inputs (links). I'm open to changing this data structure if necessary but it seems to me to work well. I've been looking at Backbone, and also Can.JS but I'm not sure if either of those are suitable for this.
Some additional information:
there's no need to update an individual item in the data structure separatly; I plan on POSTing the entire structure when it's saved. That said...
there's actually two different views, one for the dispatchers and another for their supervisors. The dispatchers only have the ability to change the campus, roads, etc conditions through drop-downs and furthermore can only change the "condition" key; each possible condition has a default status assigned to it. Supervisors can override the default status, and have access to the announcements, sidebar and links keys. Maybe I do need to rethink the previous point about POSTing the whole thing at once?
the supervisors need to be able to add and remove links, as well as add and remove entire link categories. This means that DOM elements need to be added and removed, which is why I'm thinking of using something like Backbone or Can.js instead of just writing some ghetto solution that looks at all the form elements and builds the appropriate JSON to POST to the server.
Suggestions welcomed!
CanJS works great with nested data. can.Model is inheriting can.Observe which allows you to listen to any changes in the object structure.
If you include can.Observe.Delegate you have even more powerful event mechanism (example from the docs):
// create an observable
var observe = new can.Observe({
name : {
first : "Justin Meyer"
}
})
var handler;
//listen to changes on a property
observe.delegate("name.first","set",
handler = function(ev, newVal, oldVal, prop){
this //-> "Justin"
ev.currentTarget //-> observe
newVal //-> "Justin Meyer"
oldVal //-> "Justin"
prop //-> "name.first"
});
// change the property
observe.attr('name.first',"Justin")

Categories