Is it possible to create an input widget in app maker? Or how to make a multiselect with numbers? - google-app-maker

I want to have an input widget that is similar to the built-in multiselect input widget but where instead of checks a number is given, say for example in the pizza order app example, one would be able to pick 3 for the first topping, 0 for the second topping and 1 for the third topping.
Since input widgets are not modifiable and display widgets do not have the "value" field, I thought I could do it through the "submit" button event, but that uses widget.datasource.createItem() which is quite opaque and I don't know how I would get the data from the display widget and integrate it to create an item.

Based on your requirement, I created a simple implementation using a list widget and a client-side calculated model. I also used a multi-select widget to show the dynamic mapping of selections to the actual input widget.
Editor View
From a selected list of toppings, the calculated model will be populated and render the sublist of toppings together with an input field for the user to enter the number of desired toppings.
The multi-select widget is bound to a parameter in the datasource.
Here is the query function to populate the list onValueChange.
function generateTopingList(query,recordFactory,callback) {
var toppingList = [];
if(query.parameters.topingList){
query.parameters.topingList.forEach(function(e,i){
var newRecord = recordFactory.create();
newRecord.Name = e;
newRecord.Amount = 0;
toppingList.push(newRecord);
});
}
callback.success(toppingList);
}
The list widget will make use of this datasource and bind the name and amount field into a label and a text input.
Preview
I have a button to emulate a SAVE action To capture the entered values and display it in another label.
function showResults(selectedItems,resultWidget){
resultWidget.value = " \n";
selectedItems.forEach(function(e,i){
var toppingName = e.Name;
var enteredAmount = e.Amount;
//for display only
resultWidget.value += toppingName + " - " + enteredAmount + "\n";
});
}
See this simple video on how this works in action.
With regards to creating your own input widgets, app Maker gives you an option to create re-usable sections in your app through the concept of "Page Fragments". You can implement the logic separately, like in my case it's the list widget, then wrap it into a page fragment. You can then use this fragment in your pages.

Related

How to change a dropdown to a text box for barcode scanning into a field

I have an Appmaker form to create a record that includes a many to one relation to another table. By default, the form creates a dropdown to select the related record from a list. This works fine, but I need to barcode scan (or type) the item name rather than select it.
When I change the dropdown to a text box and bind it to the related table, it greys out and becomes unusable when I preview it. (I get a circle with a line through it when hovering over.)
When I keep both the dropdown and the textbox on the same form, I can select a record from the dropdown and it populates the textbox. After that, the textbox becomes editable and works as desired.
How can I remove the dropdown and make the text box editable?
The problem is that when you bind the textbox to a relational field it is looking for a record not just a value.
My thought is you are going to want to create a text box where you enter/scan in the value and leave it unbound. then in probably the onValueChange event write a script to query the item in the related table that you are trying to relate and set that equal to the field you are trying to edit.I don't know that this code will work haven't tested it but should get you going in the right direction:
var ds = app.datasources.Parts;
ds.query.filters.Part._equals = newValue;
ds.load(function() {
if (ds.item === null) {
alert("Part not found!");
widget.root.descendants.FieldPart.value = null;
}
else {
widget.root.descendants.FieldPart.value = ds.item;
}
});

Delete many-to-many relation of nested Appmaker list item (instead of the item itself)

I have 3 tables in Cloud SQL: person,tag,person_tag
In Appmaker, I have a form widget (datasource:person) and a list widget (datasources.person.relations.tag_id) displaying text bound to datasource.item.name. This works great, showing only the tags assigned to the person selected.
I've placed a delete button on the tag list item so I can remove the tag from that person's record. However, I can't figure out how to set the onClick event to delete the relationship (person_tag record) instead of the tag itself (from the tag table). Ideas?
App Maker will generate this code to delete current item :
widget.datasource.deleteItem();
But as it is mentioned in the question we don't need to delete the item, but break the relation between the two records. In order to do this you can modify array of items and App Maker will intelligently sync your changes:
// Here widget is delete button and
// widget.parent will be list's row (or grid's cell depending on the UI)
// and by getting its position in the list/grid
// we will get index of datasource's item (relation) we need to break
var row = widget.parent;
var index = row.childIndex;
// remove one item at index, this will force
// App Maker to break the relation
app.datasources.Person.item.Tags.splice(index, 1);
You can find this pattern in Vendor Ratings template
Here's how I did it: Given a many-to-many relationship between Person and Tags, select the currently selected item from both tables. Find the index of first item within relational array, then remove it.
var person = widget.root.descendants.Table1.datasource.item;
var tag = widget.root.descendants.Table2.datasource.item;
personIndex = person.Tags.indexOf(person);
if (personIndex !== -1) person.Tags.splice(personIndex, 1);

Is it possible to load AppMaker DropDowns with an Option Text and and Value?

I've been able to set the options on an AppMaker DropDown by doing this sort of thing:
google.script.run
.withSuccessHandler(function(oA){app.pages.Notes.descendants.Dropdown1.options=oA;})
.getSelectOptions();//oA is just an array
But I'd like to know how to do load different values in the options and value like we can do it in javascript with something like this:
function updateSelect(vA){
var select = document.getElementById("sel1");
select.options.length = 0;
for(var i=0;i<vA.length;i++)
{
select.options[i] = new Option(vA[i].option,vA[i].value);
}
}
And I tried this by trying to get a hold of the dom element as follows:
var elem=app.pages.myPage.descendants.myDropDown.getElement();
elem.options.length=0;//always gives me an error because options doesn't seem to exist in that object.
So for now I've been using the standard HTML dom elements in an AppMaker Html widget and that works okay as long as your select is on the first page. If it's not on the first page I have found that the onChange event can't load Widgets on pages that are not visible. It is interesting to note however that you can change the contents of HTML widgets even if they are on other non visible pages.
Anyway the simple question is how can one load one thing into value and another thing into option text in an AppMaker DropDown Widget?
<option value="value">text</option>
If you have a predefined array for your options and values you could do the following for your onAttach Event of your dropdown:
var options = ['one thing','two thing','three thing'];
var names = ['another one thing','another two thing','another three thing'];
widget.options = options;
widget.names = names;
In this case the values that would get recorded would be the options array, but the items that would be displayed would be from the names array. Hope this gets you on the right path.

KnockOut JS - Binding a button to an item in a collection

This is a slightly tricky question to put into words. Basically I've been trying to build a shopping cart page in KnockoutJS based on one of the examples in the the KnockoutJS website (http://knockoutjs.com/examples/cartEditor.html). However I wanted to make use of jQueryUI sliders so that I could adjust the values of each product in my cart.
This I've managed to get working OK and I can add a product (in this case Motorcars) to my basket and adjust the value and also increase/decrease the value depending on whether the car has a sports kit or is a convertible.
http://jsfiddle.net/FloatLeft/UjRrJ/
However, instead of adding a product (the "Add Car" button) and then choosing the car type, I want to be able to add a specific type (eg BMW, Ford) to the cart at the click of the button (eg clicking on the "Add BMW" button - this does nothing at the moment).
However my simple brain cant work out how to bind the button to a specific car in the collection. I think I can retrieve the car by creating a function that iterates over the collection and finds the car that has the type that matches a string, e.g.
function GetCar(carType) {
for (var i = 0; i < sampleCars.length; i++) {
if (sampleCars[i].Type == carType) {
return sampleCars[i];
}
}
}
So basically I want to know how I can bind the click event of "Add BMW" button to a particular car in the collection and have that added to my cart.
If you plan on making multiple buttons, you can create a function which can create your event handlers which can take in a car type.
self.addSpecificCarLine = function (carType) {
return function () {
var car = ko.utils.arrayFirst(sampleCars, function (car) {
return car.Type === carType;
});
var cartLine = new CartLine();
cartLine.car(car);
self.lines.push(cartLine);
};
};
Then you can bind to the handlers like so:
<button data-bind='click: addSpecificCarLine("BMW")'>Add BMW</button>
Updated fiddle

target and display an object of list control in flex

i have made a list control. i want to display the name of the objects in it in a text control box
the code i am using here is
public function add(event:MouseEvent):void
{
var str:String;
str = mylistcontrol.dataProvider.getItemAt(0).toString();
mytextarea.text += str+ "has been added";
mytextarea.text += "\n";
}
The problem with this code is i am using index value of 0. however i want to display the name of object on which i have clicked or which is highlighted.
any ideas and thoughts?
When you say the name of the object do you mean the name of the ItemRenderer?
If that's the case one method you could use involves creating a custom event and a custom item renderer...
Create a custom ItemRenderer when clicked dispatch your CustomEvent which would a have a data property into which you can put anything you like.

Resources