Dashboard into StackPanel - google-apps-script

I am getting a 'Object Type doesn't match Column Type' error and not sure why... not sure if its something wrong in my code (more than likely) or if it just won't accept the dashboard. I am thinking that my error has to do with the Data Source and how I'm pulling the data from the spreadsheet.
function doGet() {
var app = UiApp.createApplication().setTitle('DHS: Kurzweil Calendar');
//Create stack panel
var stackPanel = app.createStackPanel().setSize('100%', '100%');
var info = about(app);
var p1 = app.createVerticalPanel().setId('vrtPanel1').add(info);
var cal = calendar(app);
var p2 = app.createVerticalPanel().setId('vrtPanel2').add(cal);
var form = formBuild(app);
var p3 = app.createVerticalPanel().setId('vrtPanel3').add(form);
//add widgets to each stack panel, and name the stack panel
stackPanel.add(p1, 'About the Lab');
stackPanel.add(p2, 'Lab Calendar');
stackPanel.add(p3, 'Lab Scheduling');
//Add the panel to the application
app.add(stackPanel);
return app;
}
function about(app){
return app.createHTML('<br />' +
'<p>The Kurzweil Lab at Davie High School supports <i>20 independent student workstations</i> and is designed for the specific use of Kurzweil software. The lab\'s main objective is to support students who have a Read-Aloud accommodation on their Individual Education Plan (IEP). If a student does not have a Read-Aloud accommodation, but has another accommodation like: Separate Setting, Extended Time, or English as a Second Language (ESL) then they are welcome in the lab as long as the lab is not full. If the lab reaches capacity and Read-Aloud students need to use Kurzweil, the student(s) without a Read-Aloud accommodation or who are refusing their Read-Aloud accommodation will be asked to go back to their classroom so that the teacher can make other arrangements for that student.</p>' +
'<p>During non-testing situations the Kurzweil Lab can be scheduled by EC teachers to help with study skills, individual projects, or other work that requires the use of a computer lab.</p>', true);
}
function calendar(app){
// Create Data Source
var ss = SpreadsheetApp.openById('0Aur3owCpuUY-dGJIOGZ1LXhqT2FNMGVXSGNJazFnUmc');
var datasource = ss.getSheetByName('Schedule').getRange(1,1,ss.getLastRow(),ss.getLastColumn());
// Create Charts and Controls
var dateFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Date").build();
var teacherFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Teacher").build();
var subjectFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Subject").build();
var periodFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Period").build();
var typeFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Type").build();
var tableChart = Charts.newTableChart().build();
//Create and bind Dashboard
var dashboard = Charts.newDashboardPanel()
.setDataTable(datasource)
.bind([dateFilter, teacherFilter, subjectFilter, periodFilter, typeFilter], [tableChart])
.build();
//Create Application
dashboard.add(app.createVerticalPanel()
.add(app.createHorizontalPanel()
.add(dateFilter).add(teacherFilter).add(subjectFilter).add(periodFilter).add(typeFilter)
.setSpacing(70))
.add(app.createHorizontalPanel()
.add(tableChart)
.setSpacing(10)));
//Add the panel to the application
app.add(dashboard);
return app;
}

You simply forgot that you changed the way every function that build the UI returns data... If you remember your first post about stackPanels we changed the call to
var cal = calendar(app);
and then
var p2 = app.createVerticalPanel().setId('vrtPanel2').add(cal);
So we clearly expect to get a Ui object (a widget) in return.
You can simply change the end of the function calendar(app){ like below :
...
dashboard.add(app.createVerticalPanel()
.add(app.createHorizontalPanel()
.add(dateFilter).add(teacherFilter).add(subjectFilter).add(periodFilter).add(typeFilter)
.setSpacing(70))
.add(app.createHorizontalPanel()
.add(tableChart)
.setSpacing(10)));
//Add the panel to the application
return dashboard;// return the dashboard itself, not the app.
}
EDIT : this was definitely to simple to be true... my answer was correct but obviously didn't include the issues with the dashboard building.
After a few researches (I've never used Charts service before) I came to this code that produces no errors but I'm definitely not sure it returns what you wanted...
Nevertheless it should help you to find your way. (don't blame me if it doesn't look right ;-)
function calendar(app){
// Create Data Source
var ss = SpreadsheetApp.openById('0Aur3owCpuUY-dGJIOGZ1LXhqT2FNMGVXSGNJazFnUmc');
var sh = ss.getSheetByName('Schedule');
var datasource = sh.getRange(1,2,sh.getLastRow(),sh.getLastColumn()).getValues();
Logger.log(datasource)
var dataTable = Charts.newDataTable();
for( var j in datasource[0] ){
dataTable.addColumn(Charts.ColumnType.STRING, datasource[0][j]);
}
for( var i = 1; i < datasource.length; ++i ){
dataTable.addRow(datasource[i].map(String));
}
var dashboard = Charts.newDashboardPanel().setDataTable(dataTable); // Create Charts and Controls
var dateFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Date").setDataTable(dataTable).build();
var teacherFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Teacher").setDataTable(dataTable).build();
var subjectFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Subject").setDataTable(dataTable).build();
var periodFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Period").setDataTable(dataTable).build();
var typeFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("Type").setDataTable(dataTable).build();
var tableChart = Charts.newTableChart().setDimensions(1000, 600).setDataTable(dataTable).build();
//Create and bind Dashboard
var dashboard = Charts.newDashboardPanel()
.setDataTable(dataTable)
.bind([dateFilter, teacherFilter, subjectFilter, periodFilter, typeFilter], [tableChart])
.build();
//Create Application
var dashBoardPanel = app.createVerticalPanel()
dashBoardPanel.add(app.createHorizontalPanel()
.add(dateFilter).add(teacherFilter).add(subjectFilter).add(periodFilter).add(typeFilter)
.setSpacing(30));
dashBoardPanel.add(tableChart);
//Add the panel to the application
return dashBoardPanel;
}
EDIT 2 : to get the first column as a date you have to slightly modify the for loops that populate the dataTables so that you can convert to string only from the second column.
I did it like this :
function calendar(app){
// Create Data Source
var ss = SpreadsheetApp.openById('0Aur3owCpuUY-dGJIOGZ1LXhqT2FNMGVXSGNJazFnUmc');
var sh = ss.getSheetByName('Schedule');
var datasource = sh.getRange(1,1,sh.getLastRow(),sh.getLastColumn()).getValues();
Logger.log(datasource)
var dataTable = Charts.newDataTable();
dataTable.addColumn(Charts.ColumnType.DATE, datasource[0][1]);
for( var j=2 ;j< datasource[0].length ;++j ){
dataTable.addColumn(Charts.ColumnType.STRING, datasource[0][j]);
}
for( var i = 1; i < datasource.length; ++i ){
var datarow = [];
datarow.push(datasource[i][1]);
for( var j=2 ;j< datasource[0].length ;++j ){
datarow.push(datasource[i][j].toString());
}
dataTable.addRow(datarow);
}
var dashboard = Charts.newDashboardPanel().setDataTable(dataTable); // Create Charts and Controls
...

Related

An alternative way to pass data (eg, array values) through handler without using ScriptProperties

I built an app in which I use ScriptProperties to store data from a handler to its but(e) function. This was working nice, until other people started using the same spreadsheet at the same time. So often happens that one person is taking a time thinking about what item choose from a checkbox menu and another person uses the same function, changing the data stored at scriptProperties and affecting the use of the function by the first person.
What is the best way to fix it, using an alternative way to pass information through the handler?
Here one sample of one of theese functions (in which I'm using ScriptProperties to pass the values ofletterSpreadsheetId and recipientArray):
function letter(letterSpreadsheetId){
ScriptProperties.setProperty('letterSpreadsheetId', letterSpreadsheetId); // different people may have different letterSpreadsheetId;
ScriptProperties.setProperty('letter', 1); // to be used in another function
var activeSheet = ss.getActiveSheet();
var app = UiApp.createApplication().setHeight(400).setWidth(600);
var panel = app.createVerticalPanel(); // you can embed that in a form panel
var label = app.createLabel("Choose a receiver").setStyleAttribute("fontSize", 18);
app.add(label);
var sheet = SpreadsheetApp.openById(letterSpreadsheetId).getSheetByName("receivers");
var recipientArray = sheet.getRange(2, 1, sheet.getLastRow(), sheet.getLastColumn()).getValues();
var item3Panel = app.createHorizontalPanel();
item3Panel.add(app.createLabel("receiver"));
var listBox = app.createListBox().setName('item3');
for(var i = 0; i < (recipientArray.length); i++){
listBox.addItem(recipientArray[i][1]);
}
item3Panel.add(listBox);
var recipientArrayStr = JSON.stringify(recipientArray);
ScriptProperties.setProperty('recipientArr', recipientArrayStr);
var handlerBut = app.createServerHandler("butAnswerLetter").addCallbackElement(panel);
var but = app.createButton("submit").setId("submitButton2").addClickHandler(handlerBut);
panel.add(item1Panel)
.add(item2Panel)
.add(item3Panel)
.add(but)
.add(app.createLabel().setId("answer"));
var scroll = app.createScrollPanel().setPixelSize(600, 400).setTitle("My title 1");
scroll.add(panel);
app.add(scroll);
ss.show(app);
}
function butAnswerLetter(e){
var letterSpreadsheetId = ScriptProperties.getProperty('letterSpreadsheetId');
var recipient = e.parameter.item3;
ScriptProperties.setProperty('recipient', recipient);
var recipientArrayRecovery = ScriptProperties.getProperty('recipientArr');
var recipientArray = JSON.parse(recipientArrayRecovery);
for(var i=0;i<recipientArray.length;i++){
if(recipient == recipientArray[i][1]){
var usedRecipientArray = recipientArray[i];
}
}
You have 2 possibilities (that I know), either use userProperties instead of script-Properties as these are associated with the user but it will require the user to login and authorize, or - and this will work in every case even if the app is accessed anonymously, use the tags that you can write on almost any widget.
the syntax is quite simple, here is a small code example :
function doGet(){
var app = UiApp.createApplication().setTitle('test_TAG');
var list = app.createListBox(true).setVisibleItemCount(5).setPixelSize(30,450).setName('list');
var handler = app.createServerHandler('show').addCallbackElement(list);
list.addChangeHandler(handler);
var data = [];
for(var n = 0;n<20;n++){
list.addItem(n+' ');
data.push('available value = '+Number(n+1));
}
list.setTag(data.toString());
app.add(list);
return app
}
function show(e){
var app = UiApp.getActiveApplication();
var data = e.parameter.list_tag.split()
var selected = e.parameter.list;
app.add(app.createTextBox().setText(selected).setPixelSize(200,20));
app.add(app.createTextArea().setText(data.join()).setPixelSize(200,300));
return app;
}
testable here
Edit
following Zig's pertinent comment :
I forgot to mention the hidden widget (or a textBox / area set to invisible, useful for debugging when you want to check what it contains ! ) that is also useable of course...
The comment about a user having multiple windows showing the same app is also worth mentioning !
All in all you have 3 possibilities after all !
(thanks to Zig Mandel)

GUI form does not show up

I'm stuck... My code doesn't want to show me my GUI form.
If I'm trying to add this line: sh=SpreadsheetApp.getActive() before sh.show(app) - script works fine in the script editor. But! If I'm trying to deploy as a web app - script doesn't work.
function doGet() {
var app = UiApp.createApplication().setTitle('test online').setHeight(400).setWidth(600);
var dFormat = UiApp.DateTimeFormat.DATE_LONG
var sh = SpreadsheetApp.openById(spreadsheetID);
var settings = sh.getSheetByName('Name');
var lastrowTime = sh.getSheetByName('Name').getLastRow();
var settings = settings.getRange("A2:A" + lastrowTime).getValues();
var main2 = app.createGrid(1, 4);
var status = app.createLabel().setId('status').setWidth('200');
var card = app.createTextBox().setName('card').setId('card').setWidth('50');
var main1 = app.createGrid(6, 3);
var placeA = app.createTextBox().setId('placeA').setName('placeA').setWidth('400');
var placeB = app.createTextBox().setId('placeB').setName('placeB').setWidth('400');
var phone = app.createTextBox().setId(('phone')).setName('phone').setWidth('200');
var timeTo = app.createListBox(false).setWidth(200).setName('timeTo').addItem("...").setVisibleItemCount(1);
for (var i = 0; i < settings.length; i++) {
timeTo.addItem(settings[i]);
}
var main = app.createGrid(4, 5);
var date = app.createDateBox().setName('date').setFormat(dFormat);
var hour = app.createListBox().setName('hour').setWidth('100');
var min = app.createListBox().setName('min').setWidth('100');
for (h=0;h<24;++h){
if(h<10){var hourstr='0'+h}else{var hourstr=h.toString()}
hour.addItem(hourstr)
}
for (m=0;m<60;++m){
if(m<10){var minstr='0'+m}else{var minstr=m.toString()}
min.addItem(minstr)
}
var refresh = app.createButton('Refresh')
var button = app.createButton('Submit')
var main3 = app.createGrid(1,3);
var price = app.createLabel().setId('price').setWidth('400');
var finalStatus = app.createLabel().setId('finalPrice').setWidth('400');
main2.setWidget(0,0, app.createLabel('Client card: ')).setWidget(0,1, card).setWidget(0,3, status);
main1.setWidget(1,0, app.createLabel('From')).setWidget(1,1,placeA);
main1.setWidget(2,0, app.createLabel('To')).setWidget(2,1,placeB);
main1.setWidget(4,0, app.createLabel('Mobile')).setWidget(4,1,phone);
main1.setWidget(5,0, app.createLabel('Make a call?')).setWidget(5,1,timeTo);
main.setWidget(1,0,app.createLabel('Data')).setWidget(1,1,app.createLabel('hour')).setWidget(1,2,app.createLabel('min'))
main.setWidget(2,0,date).setWidget(2,1,hour).setWidget(2,2,min)
main.setWidget(2,3,refresh).setWidget(2,4, button)
main3.setWidget(0,0, price);
main3.setWidget(0,1, finalStatus);
var serverHandler = app.createServerHandler('show').addCallbackElement(main).addCallbackElement(main1).addCallbackElement(main2).addCallbackElement(main3);
button.addClickHandler(serverHandler)
var handler1 = app.createServerHandler('refresh').addCallbackElement(main).addCallbackElement(main1).addCallbackElement(main2).addCallbackElement(main3);
refresh.addClickHandler(handler1)
var handler2 = app.createServerHandler('checkDate').addCallbackElement(main).addCallbackElement(main1).addCallbackElement(main2).addCallbackElement(main3);
date.addValueChangeHandler(handler2)
app.add(main2)
app.add(main1)
app.add(main)
app.add(main3)
sh.show(app)
}
The methods that you are using to show your UI are specifically for Spreadsheet containers. You've probably read this, to get where you are, but re-read Creating User Interface Elements in UI Service, especially the examples of doGet().
function doGet() { // A script with a user interface that is published as a web app
// must contain a doGet(e) function.
...
return myapp;
}
At the end of the function, you simply need to return your UI App instance. No need to call show, or reference the spreadsheet at all.

Google Apps Scrollpanel not updating with information

My script is iterating through some spreadsheet information. I read the documentation and the scrollpanel is only allowed one child. I therefore wrapped the horizontal panel information inside a scrollpanel but for some reason the scrollpanel never shows up with contents just the colored background. Any ideas why this may be?
var myscrollpanel = app.createScrollPanel().setPixelSize(100, 100);
myscrollpanel.setWidth("100%");
myscrollpanel.setStyleAttribute("background", "silver");
var vpanel = app.createVerticalPanel();
for (i=1; i <= mylastrow;++i)
{
var cellsname= mydatarange.getCell(i,1).getValue().toLowerCase();
// Browser.msgBox(cellsname );
// Browser.msgBox(searchstr.toString());
if (cellsname.toString() == searchstr.toString())
{
var panelrow = app.createHorizontalPanel();
var ddate = app.createTextBox();
var sbehavior = app.createTextBox();
var sconsequence = app.createTextBox();
var scomment = app.createLabel();
var steacher = app.createTextBox();
ddate.setText(mydatarange.getCell(i,5).getValue());
sbehavior.setText(mydatarange.getCell(i,8).getValue());
sconsequence.setText(mydatarange.getCell(i,6).getValue());
scomment.setText(mydatarange.getCell(i,10).getValue());
steacher.setText(mydatarange.getCell(i,7).getValue());
panelrow.add(ddate);
panelrow.add(sbehavior);
panelrow.add(sconsequence);
panelrow.add(steacher);
panelrow.add(scomment);
vpanel.add(panelrow);
app.add(panelrow);
cnt = ++cnt;
}
}
// Browser.msgBox(cnt);
myscrollpanel.add(vpanel);
app.add(myscrollpanel);
// return myscrollpanel;
return app ;// update UI
there are a few "anomalies" in your code that could cause some issues, I suggest a couple of changes (see code below).
Another point is that it is not a good idea to read a spreadsheet in a loop, it is mush more efficient to read the whole range in one time and then use the array values to iterate.
Here is a code proposal, I didn't test it (and it will probably need some debugging) but put a few comments to explain the changes.
var myscrollpanel = app.createScrollPanel()//.setPixelSize(100, 100);// 100 pixel is quite small to put all the items you add !!
myscrollpanel.setWidth("100%");//
myscrollpanel.setStyleAttribute("background", "silver");// this will not affect the widgets you add to the panel...
var vpanel = app.createVerticalPanel();
var data = mydatarange.getValues();// get all data in an array
for (i=0; i <data.length;++i) // and work directly with array values (indexed to 0 instead of cells indexed to 1)
{
var cellsname= data[i][0].toString().toLowerCase();
if (cellsname == searchstr.toString()){
var panelrow = app.createHorizontalPanel();
var ddate = app.createTextBox();
var sbehavior = app.createTextBox();
var sconsequence = app.createTextBox();
var scomment = app.createLabel();
var steacher = app.createTextBox();
ddate.setText(data[i][4].getValue());
sbehavior.setText(data[i][7].getValue());
sconsequence.setText(data[i][5].getValue());
scomment.setText(data[i][9].getValue());
steacher.setText(data[i][6].getValue());
panelrow.add(ddate);
panelrow.add(sbehavior);
panelrow.add(sconsequence);
panelrow.add(steacher);
panelrow.add(scomment);
vpanel.add(panelrow);// add only to the panel, not to the app or the row will be outside the panel
cnt = ++cnt;
}
}
myscrollpanel.add(vpanel);
app.add(myscrollpanel);
return app ;// update UI
}

Google Script Error - Cannot find method add

I have been puzzled by this error. I have not been able to figure out what I am missing. Without the calls to headPanel the UI was working but would not insert the title or text label so I added the Horizontal panel in hopes of adding the text, but alas error. Please help me with this problem and I need to know what I am messing up.
function doGet(e){
var app = UiApp.createApplication();
var headPanel = app.createHorizontalPanel().setId('headPanel');
var header = app.setTitle('Detention Attendance');
var label = app.createLabel("Please enter attendance for Detention by clicking the checkbox next to the student's name if they were present. Then click Sumbit.");
headPanel.add(header); //* ERROR OCCURS HERE
headPanel.add(label);
app.add(pane);
var panel = app.createVerticalPanel();
var flexTable = app.createFlexTable().setStyleAttribute('border', '2px solid black')
.setStyleAttribute('borderCollapse','collapse')
.setBorderWidth(2);
//Get Data from spreadsheet
var spreadsheetId = 'xxxxxxxxxxxxxxxxxxxxxxxx';//Change it to your Spreadsheet ID
var dataArray = getData(spreadsheetId);
//Load data into table cells
Logger.log(dataArray);
for (var row = 0; row<dataArray.length; row++){
if (row > 0) {
var ticketDate = dataArray[row] [0];
var dateStamp = Utilities.formatDate(ticketDate, "America/Chicago", "MM/dd/yyyy");
Logger.log("dateStamp = " +dateStamp);
dataArray[row] [0] = dateStamp;
var ticketDate2 = dataArray[row] [16];
var dateStamp2 = Utilities.formatDate(ticketDate2, "America/Chicago", "MM/dd/yyyy");
dataArray[row] [16] = dateStamp2;
Logger.log("DateStamp = " +dateStamp2);
}
flexTable.setStyleAttribute("color", "purple").setText(row, 2, dataArray[row][2].toString()).setWidth('300px');
flexTable.setText(row, 0, dataArray[row][0].toString()).setWidth('600px');
flexTable.setText(row, 4, dataArray[row][16].toString()).setWidth('300px');
}
panel.add(flexTable);
app.add(panel);
return app;
}
function getData(spreadsheetId){
var ss = SpreadsheetApp.openById(spreadsheetId);
var sheet = ss.getSheets()[0].getDataRange();
Logger.log(sheet);
return sheet.getValues();
}
Your header var is a UiInstance - in fact it's the same instance as app, returned as a convenience for chaining by the call to .setTitle().
The .add() method is looking for a Widget as a parameter, and not finding it.
You don't need to keep that header var - it's only causing you trouble. In fact, you could set the Title as you create the UiApp instance:
var app = UiApp.createApplication().setTitle('Detention Attendance');

Display a pop up UI based on users' answer

I currently have a UI with drop down questions. When a user select a certain answer in the drop down list, I want to show another UI that will allow the user to answer more questions. Then, I would like to close this window and return the user to the first UI and continue answering questions.
I have tried popuppanel, set one Ui's invisibility to false but nothing seems to work.
NOTE: Since the data in my first UI are dynamic, I can't use the GUI builder so please only provide solutions using code.
These are the code I have so far:
// when user select this drop down option, show another UI
case 'Move to a special meeting':
displayActionItemsUI();
cellStatus.offset(numOfRowsOffset,0).setValue(N);
cellMeetingType.offset(numOfRowsOffset,0).setValue('Special Meeting');
break;
function displayActionItemsUI() {
var app = UiApp.getActiveApplication();
var panelActionItems = app.createVerticalPanel();
var gridActionItems = app.createGrid(3, 2).setId('gridActionItems')
.setCellPadding(15);
var lblTaskStatement = app.createLabel('Task Statement:');
var lblOwner = app.createLabel('Owner:');
var lblDeadline = app.createLabel('Deadline:');
var tboxTask = app.createTextBox().setId('tboxTask').setName('tboxTask');
var tboxOwner = app.createTextBox().setId('tboxOwner').setName('tboxOwner');
var dboxDeadline = app.createDateBox()
.setFormat(UiApp.DateTimeFormat.DATE_SHORT)
.setId('dboxDeadline').setName('dboxDeadline');
gridActionItems.setWidget(0, 0, lblTaskStatement);
gridActionItems.setWidget(0, 1, tboxTask);
gridActionItems.setWidget(1, 0, lblOwner);
gridActionItems.setWidget(1, 1, tboxOwner);
gridActionItems.setWidget(2, 0, lblDeadline);
gridActionItems.setWidget(2, 1, dboxDeadline);
var btnAdd = app.createButton('Add');
var lblTest = app.createLabel().setId('lblTest').setVisible(false);
panelActionItems.add(gridActionItems)
.add(btnAdd).add(lblTest);
app.add(panelActionItems);
addHandler = app.createServerHandler('_responseToAdd')
.addCallbackElement(panelActionItems);
btnAdd.addClickHandler(addHandler);
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.show(app);
}
// add response to a separate tab and close the UI
function _responseToAdd(e) {
// store user's inputs;
var actionItems = [];
var actionObject = new Object();
var taskStatement = e.parameter.tboxTask;
var owner = e.parameter.tboxOwner;
var deadline = e.parameter.dboxDeadline;
actionObject['task'] = taskStatement;
actionObject['owner'] = owner;
actionObject['deadline'] = deadline;
actionItems.push(actionObject);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Action Items");
var headers = ['task', 'owner', 'deadline'];
var valuesR = ObjApp.objectToArray(headers, actionItems); //returns [[]]
sheet.getRange(sheet.getLastRow()+1, 1, 1, valuesR[0].length).setValues([valuesR[0]]);
var app = UiApp.getActiveApplication();
var panelActionItems = app.getElementById('panelActionItems');
panelActionItems.clear();
return app;
}
I think you could do it using multiple panels like in this post answer, you could build the panels and change their content depending of the answers...