Open new UI without closing the actual opened Ui - google-apps-script

What I want is simply that when I press a button in the Actual Ui, opens a new Ui without closing the Actual Ui.
Here is a simple code that I did:
function shows(){
var app = UiApp.createApplication().setTitle("Actual Ui")
.setHeight(3000).setWidth(1350);;
var button = app.createButton('Button');
var pan = app.createHorizontalPanel();
pan.add(button)
var clickHandler = app.createServerClickHandler("ps");
button.addClickHandler(clickHandler);
clickHandler.addCallbackElement(pan);
app.add(pan);
var doc = SpreadsheetApp.getActive();
// show the app
doc.show(app)
}
function ps(e){
var apps = UiApp.createApplication().setHeight(50).setWidth(200);
apps.setTitle("New UI");
var docsss = SpreadsheetApp.getActive();
docsss.show(apps);
return apps
}
The code works perfectly but the fact that when I press the button it closes the Actual Ui and opens the new one.

You can't do it like that, here is how it works, use the same app instance and change its content.
function shows(){
var app = UiApp.createApplication().setTitle("common Ui")
.setHeight(400).setWidth(1350);;
var button = app.createButton('Button');
var pan = app.createHorizontalPanel().setId('panelUi1');
pan.add(app.createLabel(' first Ui'));
pan.add(button)
var clickHandler = app.createServerClickHandler("ps");
button.addClickHandler(clickHandler);
clickHandler.addCallbackElement(pan);
app.add(pan);
var doc = SpreadsheetApp.getActive();
// show the app
doc.show(app)
}
function ps(e){
var app = UiApp.getActiveApplication();
app.getElementById('panelUi1').setVisible(false);
app.add(app.createLabel('new Ui in the same app instance'));
return app;
}

Related

Changing a Textbox to a Button in Google Script

I'm working on a todo list program in google script. I have it so that people can type in their task in a textbox, but I want it so that once they hit the enter key, the textbox turns into a button that, that says what the task is, and they will later press when they finished that task and it will return to a textbox. I can't figure out how to make any changes to the app from inside another function.
What I have so far is:
function doGet(e) {
var app = UiApp.createApplication();
var panel = app.createAbsolutePanel().setHeight("750px").setWidth("1600px");
var button = app.createButton("swag");
var enterHandler = app.createServerKeyHandler('enterPress');
enterHandler.addCallbackElement(panel);
var box = app.createTextBox().addKeyUpHandler(enterHandler);
panel.add(box,0,0);
app.add(panel);
return app;
}
function enterPress(e){
var app = UiApp.getActiveApplication();
if (e.parameter.keyCode==13){
var button2 =app.createButton('swag');
var panel = app.createAbsolutePanel().setHeight('750px').setWidth('1600px');
panel.add(button2,0,0);
app.add(panel);
}
return app;
}
It recognizes the enter press, but the changes won't return to the main app.
You can do it like this :
note : I didn't "place" the button, I guess you have an idea on how you want them to show up...
You could also use a grid to place them... as you want.
function doGet(e) {
var app = UiApp.createApplication();
var panel = app.createAbsolutePanel().setHeight("750px").setWidth("1600px");
var enterHandler = app.createServerKeyHandler('enterPress').addCallbackElement(panel);
var button = app.createButton("confirm",enterHandler).setId('swag');
var tBox = app.createTextBox().setName('tBox').setId('tBox').setWidth(300).setStyleAttributes({'textAlign':'center'});
var bBox = app.createButton("no Text",enterHandler).setVisible(false).setId('bBox').setWidth(300);
panel.add(tBox,20,20).add(bBox,20,20).add(button,140,50);
app.add(panel);
return app;
}
function enterPress(e){
var app = UiApp.getActiveApplication();
if (e.parameter.source=='bBox'){
app.getElementById('bBox').setVisible(false);
app.getElementById('tBox').setVisible(true);
}
if (e.parameter.source=='swag'){
app.getElementById('bBox').setVisible(true).setHTML(e.parameter.tBox);
app.getElementById('tBox').setVisible(false);
}
return app;
}
Test here
Edit: code modified with placement .
EDIT2 : You could also hide the enter button, I find it nicer.
function enterPress(e){
var app = UiApp.getActiveApplication();
if (e.parameter.source=='bBox'){
app.getElementById('bBox').setVisible(false);
app.getElementById('tBox').setVisible(true);
app.getElementById('swag').setVisible(true);
}
if (e.parameter.source=='swag'){
app.getElementById('bBox').setVisible(true).setHTML(e.parameter.tBox);
app.getElementById('tBox').setVisible(false);
app.getElementById('swag').setVisible(false);
}
return app;
}

Message Box in popup form

I have a doubt,
I make a Button for Submit form and when I press the first button appear to me a message of confirmation to continue or not, but when I press "no" and the message disappear and return to form,but the first button doesn't work more.
You known that I make wrong.
thanks for all.
function doGet(){
var app = UiApp.createApplication().setTitle('Request Form');
var flow = app.createFlowPanel().setStyleAttribute("textAlign", "center").setWidth("900px");
var buttons = app.createButton('Print and Save').setId('buttons');
var handlers = app.createServerClickHandler('question').addCallbackElement(flow);
buttons.addClickHandler(handlers);
flow.add(buttons);
app.add(flow);
return app;
}
function question(e){
var app = UiApp.getActiveApplication();
var dialog = app.createPopupPanel().setModal(true).setSize(700, 100).setPopupPosition(10, 400);
var closeHandler = app.createClientHandler().forTargets(dialog).setVisible(false);
var handlersend = app.createServerClickHandler('Send');
var handleract =app.createServerClickHandler('activateAgain');
var labelp = app.createLabel('Are you sure that this information is correct?')
var buttonp1= app.createButton('yes, continue').addClickHandler(closeHandler).addClickHandler(handlersend);
var buttonp2= app.createButton('No, I want correct').addClickHandler(closeHandler).addClickHandler(handleract);
app.getElementById('buttons').setEnabled(false);
var gridp = app.createGrid(1,5);
gridp.setWidget(0, 0, labelp)
.setWidget(0,1,buttonp1)
.setWidget(0,2,buttonp2);
dialog.add(gridp)
dialog.show();
return app;
}
function activateAgain(e){
var app = UiApp.getActiveApplication();
app.getElementById('buttons').setEnabled(true);
return app;
}
function Send(e){
}
You are trying to make it happen in clientHandler which is basically a good idea but the problem is that some methods are not available in clientHandlers, for example hide() is not !
So you used setVisible(false) to hide the dialog but then you can't get it visible again easily...
All in all, I found it was easier with serverHandler and a few modifications.
Since you seem to be quite comfortable with UiApp I don't need to explain further, the code is self explanatory enough (I hope :-)
Code below : (and test HERE)
function doGet(){
var app = UiApp.createApplication().setTitle('Request Form');
var flow = app.createFlowPanel().setStyleAttribute("textAlign", "center").setWidth("900px");
var buttons = app.createButton('Print and Save').setId('buttons');
var handlers = app.createServerClickHandler('question').addCallbackElement(flow);
buttons.addClickHandler(handlers);
flow.add(buttons);
app.add(flow);
return app;
}
function question(e){
var app = UiApp.getActiveApplication();
var dialog = app.createPopupPanel().setModal(true).setSize(700, 100).setPopupPosition(10, 400).setId('dialog');
var button = app.getElementById('buttons').setEnabled(true);
var closeHandler = app.createClientHandler().forTargets(button).setEnabled(true);
var correctHandler = app.createServerHandler('hideDialog');
var handlersend = app.createServerClickHandler('Send');
var labelp = app.createLabel('Are you sure that this information is correct?')
var buttonp1= app.createButton('yes, continue').addClickHandler(handlersend);
var buttonp2= app.createButton('No, I want correct').addClickHandler(closeHandler).addClickHandler(correctHandler);
app.getElementById('buttons').setEnabled(false);
var gridp = app.createGrid(1,5);
gridp.setWidget(0, 0, labelp)
.setWidget(0,1,buttonp1)
.setWidget(0,2,buttonp2);
dialog.add(gridp)
dialog.show();
return app;
}
function hideDialog(){
var app = UiApp.getActiveApplication();
var dialog = app.getElementById('dialog');
dialog.hide();
return app;
}
function Send(e){
var app = UiApp.getActiveApplication();
var dialog = app.getElementById('dialog');
dialog.hide();
app.getElementById('buttons').setEnabled(false);
app.add(app.createLabel('send'));
return app;
}

Changing the content of a UI element with a button press

I have a Google UI App that is designed to assist entering data into a google spreadsheet where most of the rows are identical. To do so an UI panel is created and text fields are used for each column of the spreadsheet. With the push of a button these values are appended to the spreadsheet.
I would like the button to then clear the contents of a single text box and maintain the values of the others to allow for entry of the next nearly identical item. My attempts to do so have resulted in "Error encountered: Object does not allow properties to be added or changed."
I have included a simplified version below, the actual script has many text boxes but this simplified example also shares the problem.
function showNewEntryDialog() {
var app = UiApp.createApplication();
app.setTitle("Add Multiple Items");
var panel = app.createVerticalPanel();
var grid = app.createGrid(9,3);
var nameTextBox = app.createTextBox();
var serialTextBox = app.createTextBox();
nameTextBox.setName('nameTextBox').setId('nameTextBox');
serialTextBox.setName('serialTextBox').setId('serialTextBox');
var snButton = app.createButton('Add and New SN')
grid.setWidget(0,0,app.createLabel('Name'));
grid.setWidget(0,1,nameTextBox);
grid.setWidget(4,0,app.createLabel('Serial Number'));
grid.setWidget(4,1,serialTextBox);
grid.setWidget(4,2,snButton);
panel.add(grid);
var snClickHandler = app.createServerClickHandler("respondToButtonPress");
snButton.addClickHandler(snClickHandler);
snClickHandler.addCallbackElement(panel);
app.add(panel);
var doc = SpreadsheetApp.getActive();
doc.show(app);
}
function respondToButtonPress(e) {
var app = UiApp.getActiveApplication();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([e.parameter.nameTextBox,
e.parameter.serialTextBox]);
app.getElementById('serialTextBox').setText('');
// Does nothing?
app.getElementById('serialTextBox').setValue='';
// Error:Object does not allow changes
}
How can a button change the contents of a text box in the UI panel? If it cannot, in what other way can I achieve the behavior I desire?
Bryan's answer is correct but you could do it more efficiently using a clientHandler in your main function like this :
function showNewEntryDialog() {
var app = UiApp.createApplication();
app.setTitle("Add Multiple Items");
var panel = app.createVerticalPanel();
var grid = app.createGrid(9,3);
var nameTextBox = app.createTextBox();
var serialTextBox = app.createTextBox();
nameTextBox.setName('nameTextBox').setId('nameTextBox');
serialTextBox.setName('serialTextBox').setId('serialTextBox');
var snButton = app.createButton('Add and New SN')
grid.setWidget(0,0,app.createLabel('Name'));
grid.setWidget(0,1,nameTextBox);
grid.setWidget(4,0,app.createLabel('Serial Number'));
grid.setWidget(4,1,serialTextBox);
grid.setWidget(4,2,snButton);
panel.add(grid);
// a clientHandler : ----------------------------------------------------------
var cHandler = app.createClientHandler().forTargets(serialTextBox).setText('');
//-----------------------------------------------------------------------------
var snClickHandler = app.createServerClickHandler("respondToButtonPress");
snButton.addClickHandler(snClickHandler).addClickHandler(cHandler);// you can have multiple handlers on the same widget
snClickHandler.addCallbackElement(panel);
app.add(panel);
var doc = SpreadsheetApp.getActive();
doc.show(app);
}
function respondToButtonPress(e) {
var app = UiApp.getActiveApplication();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([e.parameter.nameTextBox,
e.parameter.serialTextBox]);
}
Think .setText() and .setValue() essentially do the same thing so really only need one or the other. Your .setValue='' is invalid. Should be .setValue(''). Need a return app; at the end too.

Dropdown list with error

I have this UiApp that presents the user with two different options in a dropdown list. User has two options when they select one of them another uiapp comes and displays some information, and it has a button to go back to original Menu. The problem I am having is that when I make the choices I get an error that says "Error Encountered: An unexpected error occurred." and the same happens when I click the go back button on the option 1 and 2. Is this a bug of GAS, or is it code that shouldnt be there?
Thank you!
function Menu(e) {
var app = UiApp.createApplication().setTitle(" Title");
var dropDownList = app.createListBox().setName('list').setId('list');
var infoLabel = app.createLabel('Scroll around to select the service desired').setId('infoLabel');
//addItems
dropDownList.addItem("Options");
dropDownList.addItem("Option1");
dropDownList.addItem("Option2");
var handler = app.createServerClickHandler('changeMe');
handler.addCallbackElement(dropDownList);
dropDownList.addChangeHandler(handler);
app.add(dropDownList);
app.add(infoLabel);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
return app;
}
function changeMe(e) {
if(e.parameter.list === 'Option1'){
var app1 = UiApp.createApplication();
var html1 = app1.add(app1.createHTML("<p><i>Hello you have selected Option 1</i> </p>")).setHeight(800).setWidth(600);
var button1 = app1.createButton('Go back').setId("button1");
app1.add(button1);
var handler2 = app1.createServerHandler('Menu');
button1.addClickHandler(handler2);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app1);
return app1;
}
else if (e.parameter.list === 'Option2'){;
var app2 = UiApp.createApplication();
var html2 = app2.add(app2.createHTML("Hello You have selected Option2"));
var button2 = app2.createButton('Go back').setId("button");
app2.add(button2);
var handler2 = app2.createServerHandler('Menu');
button2.addClickHandler(handler2);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app2);
return app2;
}
}
Try removing the 3 "return app" lines. This seems to work for me. The show method will automatically put it on the spreadsheet.

Listbox not opening handler

I am trying to create a menu in a listbox format where user chooses an option and then another uiapp is shown with the info they selected. I am having an issue here that when I opened google gives me an error that says Error encountered. An expected error occurred. I think it has to do with the setId part, if I remove one of the setId's the error doesnt happen. is this even possible?
function doGet(e) {
var app = UiApp.createApplication().setTitle("Services");
var dropDownList = app.createListBox().setName('list').setId('list');
var infoLabel = app.createLabel('Scroll around to select the service desired').setId('infoLabel');
var panel = app.createVerticalPanel();
//addItem fills the list
dropDownList.addItem("Option 1").setId("add");
dropDownList.addItem("Option 2");
panel.add(dropDownList);
panel.add(infoLabel);
app.add(panel);
var info = app.getElementById("add");
var handler2 = app.createServerHandler('display2');
info.addClickHandler(handler2);
app.add(dropDownList);
app.add(infoLabel);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function display2(e) {
var app = UiApp.createApplication();
var html = app.add(app.createHTML("<p><p><b>You have selected this option</b> </p>")).setHeight(220).setWidth(220);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
return app;
}
Are you deploying this as a web app or a script within a Spreadsheet?
If you are deploying this as a web app, then SpreadsheetApp.getActiveSpreadsheet() will not work - replace it with SpreadsheetApp.openById(id) where id is your spreadsheet ID which you will find in the URL when you open the file in the browser.
If you want to deploy this w/in a spreadsheet through a menu item or a simple button, then that works as is.
I was able to just copy paste your code and get the listbox part working fine -
https://docs.google.com/spreadsheet/ccc?key=0AkJNj_IM2wiPdHRYQThlaGVVSk04R052ZGNqclhEZWc#gid=0
Update -
I now understand what you are trying to do. Couple of things - you want to make sure you are adding a callback element via handler.addCallbackElement(myWidget) otherwise, you will not be able to read the value of the element. Second thing is that you don't need a server handler on each option in a dropdown list. Just having one handler will fire it for every change and you'll be able to get the option you selected.
I've cleaned up the code here below and also updated the spreadsheet to use this code.
function showUI() {
var app = UiApp.createApplication().setTitle("GeekSquad Services");
var infoLabel = app.createLabel('Scroll around to select the service desired');
var dropDownList = app.createListBox().setName('list').setId('list');
dropDownList.addItem("Option 1");
dropDownList.addItem("Option 2");
//you can add as many options here manually or dynamically
var handler = app.createServerHandler('dropDownCallback')
handler.addCallbackElement(dropDownList);
dropDownList.addClickHandler(handler);
var panel = app.createVerticalPanel();
panel.add(dropDownList);
panel.add(infoLabel);
app.add(panel);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function dropDownCallback(e) {
var app = UiApp.createApplication();
var html = app.add(app.createHTML("<b>You have selected this option</b> " + e.parameter.list));
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
Update #2 -
If you want to fork off and create different app instances thats easy (though its unclear why wouldn't just change panels).
function dropDownCallback(e) {
if(e.parameter.list === 'Option 1'){
var app = UiApp.createApplication();
var html = app.add(app.createHTML("Here for option!"));
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
else if (e.parameter.list ==== 'Option 2'){
//create and show other App here or whatever else
}
//refactor this better to not repeat code.
}