0

I would like to use Google Apps Script UiService to produce a multiple page user interface.

Here's what I've got so far:

function doGet(e) 
   {
var app=UiApp.createApplication();

  var nameLabel=app.createLabel('Name:');
  var button=app.createButton("next");//my button on clicking,trying to divert to other       UI
 var handler=app.createServerHandler("myclick");
 button.addClickHandler(handler);
 app.add(namelabel);
 app.add(button);
return app;
}

function myClick(){
//on clicking the button it should call the other ui or other html page
is there any method for that.}

How can I do this?

Rubén
  • 34,714
  • 9
  • 70
  • 166
ashishSober
  • 1,181
  • 1
  • 13
  • 23
  • I’m voting to close this question because UiApp was deprecated --> [UiApp has been deprecated. Please use HtmlService instead](https://stackoverflow.com/q/54605042/1595451) – Rubén Apr 02 '22 at 04:32

3 Answers3

1

You should look at How To Allow Users to Review Answers before Submiting Form?, which has an example that does this.

The idea is to create your UiApp with multiple Panels, then show or hide them in response to user actions, using setVisible(). (If you were using the HtmlService, you would enclose your "pages" in different <div>s, and change their display attributes. See toggle show/hide div with button?.)

The Best Practices also describes use of client-side handlers for responsiveness, so let's try that.

/**
 * Very simple multiple page UiApp. 
 * 
 * This function defines two panels, which appear to the end user
 * as separate web pages. Visibility of each panel is set to
 * control what the user sees.
 */
function doGet() {
  var app = UiApp.createApplication();

  var page1 = app.createFlowPanel().setId('page1');
  var page2 = app.createFlowPanel().setId('page2');

  // Content for Page 1
  page1.add(app.createLabel('Page 1'));
  var page1Button = app.createButton('Next Page');
  page1.add(page1Button);
  // Create client handler to "change pages" in browser
  var gotoPage2 = app.createClientHandler()
     .forTargets(page1).setVisible(false)
     .forTargets(page2).setVisible(true);
  page1Button.addClickHandler(gotoPage2);

  // Content for Page 2
  page2.add(app.createLabel('Page 2'));
  var page2Button = app.createButton('Previous Page');
  page2.add(page2Button);
  // Create client handler to "change pages" in browser
  var gotoPage1 = app.createClientHandler()
     .forTargets(page1).setVisible(true)
     .forTargets(page2).setVisible(false);
  page2Button.addClickHandler(gotoPage1);

  app.add(page1);
  app.add(page2);

  // Set initial visibility
  page1.setVisible(true);
  page2.setVisible(false);

  return app;
}

That works for changing the view of the UI. To extend this for general purposes, you would likely want to add server-side handlers to the same buttons to perform work, and update the contents of the panels as things progress.

Community
  • 1
  • 1
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
  • yeah...great mogsdad,i really appreciate that coding ..thank you so much. – ashishSober Jan 05 '14 at 19:25
  • but while we go for server-side handlers, like `var gotopage2 = app.createServerHandler("toSubmit").addCallbackelement(page1)` but after this we cannot use `.forTargets(page2).setVisible()` so how do we set the targets,as you mention that in button we can do that – ashishSober Jan 05 '14 at 21:44
  • Use both server & client handlers - you can attach multiple to an element. Only the client handler can manipulate visibility. – Mogsdad Jan 06 '14 at 14:26
1

Here is working code that demonstrates a multiple page form, i.e. it does the initial doGet() and then lets you advance back and forth doing multiple doPost()'s. All this is done in a single getForm() function called by both the standard doGet() and the doPost() functions.

// Muliple page form using Google Apps Script

function doGet(eventInfo)  {return GUI(eventInfo)};
function doPost(eventInfo) {return GUI(eventInfo)};

function GUI (eventInfo) {
  var n = (eventInfo.parameter.state == void(0) ? 0 : parseInt(eventInfo.parameter.state));
  var ui = ((n == 0)? UiApp.createApplication() : UiApp.getActiveApplication());
  var Form;
  switch(n){
    case 0: {
      Form = getForm(eventInfo,n); // Use identical forms for demo purpose only
    } break;
    case 1: {
      Form = getForm(eventInfo,n); // In reality, each form would differ but...
    } break;
    default: {
      Form = getForm(eventInfo,n) // each form must abide by (implement) the hidden state variable
    } break;
  }
  return ui.add(Form);
};

function getForm(eventInfo,n) {
  var ui = UiApp.getActiveApplication();

  // Increment the ID stored in a hidden text-box
  var state = ui.createTextBox().setId('state').setName('state').setValue(1+n).setVisible(true).setEnabled(false);
  var H1 = ui.createHTML("<H1>Form "+n+"</H1>");
  var H2 = ui.createHTML(
    "<h2>"+(eventInfo.parameter.formId==void(0)?"":"Created by submission of form "+eventInfo.parameter.formId)+"</h2>");

  // Add three submit buttons to go forward, backward and to validate the form
  var Next = ui.createSubmitButton("Next").setEnabled(true).setVisible(true);
  var Back = ui.createSubmitButton("Back").setEnabled(n>1).setVisible(true);
  var Validate = ui.createSubmitButton("Validate").setEnabled(n>0).setVisible(true);
  var Buttons = ui.createHorizontalPanel().add(Back).add(Validate).add(Next);
  var Body = ui.createVerticalPanel().add(H1).add(H2).add(state).add(Buttons).add(getParameters(eventInfo));
  var Form = ui.createFormPanel().setId((n>0?'doPost[':'doGet[')+n+']').add(Body);

  // Add client handlers using setText() to adjust state prior to form submission
  // NB: Use of the .setValue(val) and .setValue(val,bool) methods give runtime errors!
  var onClickValidateHandler = ui.createClientHandler().forTargets(state).setText(''+(parseInt(n)));
  var onClickBackHandler = ui.createClientHandler().forTargets(state).setText(''+(parseInt(n)-1));
  Validate.addClickHandler(onClickValidateHandler);
  Back.addClickHandler(onClickBackHandler);

  // Add a client handler executed prior to form submission
  var onFormSubmit = ui.createClientHandler()
  .forTargets(state).setEnabled(true) // Enable so value gets included in post parameters
  .forTargets(Body).setStyleAttribute("backgroundColor","#EEE");    
  Form.addSubmitHandler(onFormSubmit);

  return Form;
}

function getParameters(eventInfo) {
  var ui = UiApp.getActiveApplication();
  var panel = ui.createVerticalPanel().add(ui.createLabel("Parameters: "));
  for( p in eventInfo.parameter)
    panel.add(ui.createLabel(" - " + p + " = " + eventInfo.parameter[p]));
  return panel;
}

The code uses a single "hidden" state (here visualized in a TextBox) and multiple SubmitButton's to allow the user to advance forward and backward through the form sequence, as well as to validate the contents of the form. The two extra SubmitButton's are "rewired" using ClientHandler's that simply modify the hidden state prior to form submission.

Notes

  • Note the use of the .setText(value) method in the client handler's. Using the Chrome browser I get weird runtime errors if I switch to either of the TextBox's .setValue(value) or .setValue(value, fireEvents) methods.

  • I tried (unsuccessfully) to implement this logic using a Script Property instead of the hidden TextBox. Instead of client handlers, this requires using server handlers. The behavior is erratic, suggesting to me that the asynchronous server-side events are occurring after the form submission event.

Steven.AA
  • 79
  • 4
0

You could load different UI's on reading the parameters in your app. The doGet(e) passes the parameters in the app's url. This way you could call your app with for example: ?myapp=1 (url parameter). in your doGet you could read that parameter with: e.parameter.myapp This way you could load different applications depending on the parameters that where passed.

You could just change your button with a link (to your own app, with different url parameters).

You could also do it with buttons and handlers but the above way has my preference.

If you want to use a button<>handler just change you main (first panel) and each time add a completely new panel to your app object. This way you would start from scratch (i.e. create a new application).