Skip to Content

SAPUI5: How do you update a Label in a View from a json model?

Hi I need help with updating my Label in a view with new values from a json model everytime a button is clicked. How do you do this in SAPUI5?

You can see there is a question text and answer text coming from questionnaire model I would like to update from data[0].question.text to data[1].question.text which is displayed in my Toolbar text. How to achieve this in SAPUI5?

I have used toolbar header for question text and different labels for options? Is this right way? Will I able to update the toolbar header text?

My Code is as below

App.view.xml

<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form" xmlns:core="sap.ui.core"
displayBlock="true" controllerName="opensap.onlinequestionnaire.controller.App" height="100%">
<Page title="Online Questionnaire" class="sapUiContentPadding" id="myPage">
    <headerContent>
        <Button icon="sap-icon://action" tooltip="Share"/>
    </headerContent>
    <subHeader/>
    <content>
        <VBox class="sapUiSmallMargin">
            <f:SimpleForm id="SimpleFormToolbar" layout="ResponsiveGridLayout">
                <f:toolbar>
                    <Toolbar id="TB1">
                        <Title text="Question 1" level="H4" titleStyle="H4"/>
                        <ToolbarSpacer/>
                        <Button icon="sap-icon://drop-down-list"/>
                    </Toolbar>
                </f:toolbar>
                <f:content>
                    <Toolbar design="Solid">
                        <Title text="{questionnaire>/data/0/question/text}" level="H5" titleStyle="H5" textAlign="Center" id="questionText"/>
                    </Toolbar>
                    <VBox id="multipleChoiceHolder">
                        <HBox id="answerRow1">
                            <HBox width="700px" backgroundDesign="Solid" alignItems="Center" id="mCHorHolder1"><CheckBox id="checkBox1"/><Label text="Dogs" id="multipleChoice1"/></HBox>
                            <HBox width="700px" backgroundDesign="Solid" alignItems="Center" id="mCHorHolder2"><CheckBox id="checkBox2"/><Label text="Cats" id="multipleChoice2"/></HBox>
                        </HBox>
                        <HBox id="answerRow2">
                            <HBox width="700px" backgroundDesign="Solid" alignItems="Center" id="mCHorHolder3"><CheckBox id="checkBox3"/><Label text="Rabbits" id="multipleChoice3"/></HBox>
                            <HBox width="700px" backgroundDesign="Solid" alignItems="Center" id="mCHorHolder4"><CheckBox id="checkBox4"/><Label text="Hamsters" id="multipleChoice4"/></HBox>
                        </HBox>
                    </VBox> </f:content>
            </f:SimpleForm>
        </VBox>
    </content>
    <footer>
        <Toolbar id="toolBar">
            <Button text="Previous" type="Emphasized" width="300px" press="goToPrevious" icon="sap-icon://navigation-left-arrow" id="previousButton"/>
            <ToolbarSpacer/>
            <Button text="Next" type="Emphasized" width="300px" press="goToNext" icon="sap-icon://navigation-right-arrow" iconFirst="false"
                id="nextButton"/>
        </Toolbar>
    </footer>
</Page>

questionnaire.json

{ data: [{
    "question": "Which pet do you like from the following?",
    "answers": ["Cats", "Rabbits", "Dogs", "Hamsters"],
    "correct": 1
}, {
    "question": "Which pet do you prefer from the following?",
    "answers": ["Cats", "Dogs"],
    "correct": 1
}, {
    "question": "What food brand does your pet eat?",
    "answers": ["Pedigree", "Catfood", "Rabbitfood", "HamstersFood"],

    "correct": 1
}]
}  


App.controller.js

sap.ui.define([
"sap/ui/core/mvc/Controller"
], function(Controller){


Controller.extend("opensap.onlinequestionnaire.controller.App", {
    goToPrevious:function(){
        alert("Previous Question");
    },
    goToNext:function(){
        alert("Next Question");
    }
});

});

My Front end looks like this:


ui1.png (31.3 kB)
Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

3 Answers

  • Best Answer
    May 12, 2017 at 12:38 PM

    I have a few thoughts on this.

    • Give each question a serial number / key, incremental numbers like 1,2,3 for example.
    • Store important information globally like current question, previous question, current questions's answers etc.
    • Split the question string and answers array.
    • Create a 2nd JSON model to store current question from questionnaire's model, let's use the name tempModel for this example.
    • Create check boxex through JS based on answers, number of answers etc, through java script.

    Here's how the code would look. I'm assuming a few things from your post and the structure of your data. The goToPrevious function would work similarly.

    Note - this is just 1 way to do it, off the top of my head, there may be a more elegant/efficient solution, but first time around this is how I'd do it.

    Note 2- this solution is assuming you already have the 1st question up and are navigating to the next question. You'd want to run slightly different version of this on initialize or when you want to load the 1st question.

    View:

    <p><Title text="{tempModel >/question}" level="H5" titleStyle="H5" textAlign="Center" id="questionText"/><br>	</p><p><f:SimpleForm id="simpleFormID" editable="true" title="" layout="ResponsiveGridLayout" 
    		minWidth="1024" labelSpanL="3" labelSpanM="3" labelSpanS="2"
    		emptySpanL="2" emptySpanM="2" emptySpanS="1">
    		<f:content>
    	
    		</f:content>
    	</f:SimpleForm>
    </p>

    Controller:

    currentQ: null,  // Store the current question's object
    previousQ: null, // Store the previous question's object
    currentAnswers: null, // Store all possible answers for current Q
    correctAnswer: null, // Store the correct answer for current Q
    
    goToNext: function() {
            var curQ = this.currentQ;
            var q = questionnaireModel.getData() // the JSON object with question, answers, correct and key properties
            
            if (curQ = q.length-1) {    // check if last question assuming key starts from 1
                MessageBox.show("End of questions")
                return;
            }
            var checkArr = [] // Store check boxs data
            q.forEach(function(i) { 
    	    if (i.key === curQ + 1) {
                    var obj = {}
                    obj.["question"] = i.question
                    obj.["key"] = i.key
                    checkArr = i.answers
                    this.currentAnswers = i.answers // store all current answers options globally.
                    this.correctAnswer = i.correct // store position of current correct answer.
                    this.currentQ = i.key // update current question key with next question's key
                    this.previousQ = curQ // udpate previous question key with current question's key
                    
                    sap.ui.getCore().getModel("tempModel").setData(obj) // set question to tempModel bound to label
                    sap.ui.getCore().getModel("tempModel").refresh() // refresh model to update new question in view
                }
            });
          
          	var oSimpleForm = this.getView().byId("simpleFormID")  // Simple form to store controls. I like SFs because of its automatic layout features
            
          	checkArr.forEach(function(chk, index){
              
              var i = index;
              if ((++i).toString() === this.correctAnswer) { // increment index to match answer's position in array which starts at 1 instead of 0
              	this.correctAnswer = chk // overwrite current correct answer's position with actual correct answer.
              }
              
              var oLabel = new sap.m.Label({
                	text: chk
              });
              
              var oCheckBox = new sap.m.CheckBox(chk{  // create check box with value as id
               		editable: false
                    select: jQuery.proxy(this.onCheckBoxSelect, this)                             
               });
               oSimpleForm.destroyContent(); // Destroy any previous content before adding new controls
          	   oSimpleForm.addContent(oLabel);
               oSimpleForm.addContent(oCheckBox);
            });
    	},
    
        onCheckBoxSelect: function(oEvent) {
          var answer = oEvent.getSource().sId // ID of selected checkbox which will also be the correct answer.
        	
          if ( answer === this.correctAnswer ) {
            	*Do something*
          }
        
        },
    
    Add comment
    10|10000 characters needed characters exceeded

  • May 12, 2017 at 09:15 AM

    Use the CheckBox with text option to you can easily pull up the selected option by the user and get the relevant text.

    You can update any data bound to the controls. So, first build the local model and bind to the screens.

    Then, in the nextQuestion method, modify the model and that will change the display.

    After clicking every question, maintain the user entries in a separate model which can be used to update the backend.

    Regards,

    Sharath

    Add comment
    10|10000 characters needed characters exceeded

  • May 15, 2017 at 10:01 AM

    @Abdul Moh'd

    Hi I like the idea what you are stating but the code which you showed is a bit hard for me to understand as my coding skills in javascript and SAPUI5 are of beginner level. I will show you what I did.

    As you suggested I created a separate json Model named currentQuestion.json which holds the current question with properties index, questions.
    Now in my setNext() I am able to set the question present on 0th index that is "Which pet do you like from the following?" question to my currentQuestion.question property.
    So now my currentQuestion has index = 0, question = "Which pet do you like from the following?".
    But now how do I increment this index to next value on the click of goToNext() and update the question to next question and display it in the <Title text="{questionnaire>/data/0/question}" level="H5" titleStyle="H5" textAlign="Center" id="questionText"/> .
    This I am unable to achieve.


    App.view.xml:

    <f:SimpleForm id="SimpleFormToolbar" layout="ResponsiveGridLayout">
       <f:toolbar>
    	<Toolbar id="questionNumberHolder">
    		<Title text="Question 1" level="H4" titleStyle="H4"/>
    	<ToolbarSpacer/>
    		<Button icon="sap-icon://drop-down-list"/>
            </Toolbar>
       </f:toolbar>
       <f:content>
    	<Toolbar design="Solid" id="questionTextHolder">
    		<Title text="{questionnaire>/data/0/question}" level="H5" titleStyle="H5" textAlign="Center" id="questionText"/> 
    	</Toolbar>
    		<VBox id="answersHolder">
    			<items id="answerChoices">
    				<VBox id="multipleChoices">
    				    <items>
    					<HBox backgroundDesign="Solid" alignItems="Center">
    				           <items>
    						<CheckBox id="mCheckBox0"></CheckBox><Label text="{questionnaire>/data/0/answers/0}" id="multipleChoice0" width="500px"></Label>
    						<CheckBox id="mCheckBox1"></CheckBox><Label text="{questionnaire>/data/0/answers/1}" id="multipleChoice1" width="500px"></Label>
    				           </items>
    					</HBox>
    					<HBox backgroundDesign="Solid" alignItems="Center">
    					    <items>
    						<CheckBox id="mCheckBox2"></CheckBox><Label text="{questionnaire>/data/0/answers/2}" id="multipleChoice2" width="500px"></Label>
    						<CheckBox id="mCheckBox3"></CheckBox><Label text="{questionnaire>/data/0/answers/3}" id="multipleChoice3" width="500px"></Label>
    					    </items>
    					</HBox>
    				   </items>
    			         </VBox>
    .... </Page>
    </mvc:View>

    questionnaire.json

    {
    	"data": [{
    		"question": "Which pet do you like from the following?",
    		"answers": ["Cats", "Rabbits", "Dogs", "Hamsters"],
    		"correct": 1
    	}, {
    		"question": "Which pet do you prefer from the following?",
    		"answers": ["Cats", "Dogs"],
    		"correct": 1
    	}, {
    		"question": "What food brand does your pet eat?",
    		"answers": ["Pedigree", "Catfood", "Rabbitfood", "HamstersFood"],
    		"correct": 1
    	}]
    }
    

    App.controller.js

    sap.ui.define([
    	"sap/ui/core/mvc/Controller",
    	"sap/ui/model/json/JSONModel"
    ], function(Controller, JSONModel) {
    
    
    	var oCurrentQuestionModel;
    	var oQuestionModel;
    	var iCurrentIndex;
    
    
    	Controller.extend("opensap.onlinequestionnaire.controller.App", {
    		onInit: function() {
    			this.questionSetUp();
    			this.getView().setModel(new JSONModel({
    				index: false,
    				question: {}
    			}), "currentQuestion");
    		},
    		goToPrevious: function() {
    			//alert("Previous Question");
    			this.byId("multipleChoices").setVisible(true);
    			this.byId("singleChoices").setVisible(false);
    		},
    		goToNext: function() {
    			//alert("Next Question");
    			//alert(this.byId("mC"));
    			this.setNext();
    			this.byId("multipleChoices").setVisible(false);
    			this.byId("singleChoices").setVisible(true);
    		},
    		questionSetUp: function() {
    			this.byId("multipleChoices").setVisible(true);
    			this.byId("singleChoices").setVisible(false);
    			this.byId("textInput").setVisible(false);
    		},
    		setNext: function() {
    			oCurrentQuestionModel = this.getView().getModel("currentQuestion");
    			oQuestionModel = this.getOwnerComponent().getModel("questionnaire");
    			iCurrentIndex = oCurrentQuestionModel.getProperty("/index");
    			//console.log(iCurrentIndex);
    			//console.log(oQuestionModel.getProperty("/data/0/question"));
    			if (iCurrentIndex) {
    				++iCurrentIndex;
    			} else {
    				iCurrentIndex = 0;
    			}
    			//iCurrentIndex = iCurrentIndex ? ++iCurrentIndex : 0;
    			this.setCurrentQuestionModel();
    			this.byId("questionText").setText(oCurrentQuestionModel.getProperty("/question"));
    
    
    			console.log(oCurrentQuestionModel.getProperty("/question"));
    			console.log(oCurrentQuestionModel.getProperty("/"));
    		},
    		setCurrentQuestionModel: function() {
    			var oCurrent = {
    				index: iCurrentIndex,
    				//index: i,
    				question: oQuestionModel.getProperty("/data/" + iCurrentIndex + "/question")
    					//question: oQuestionModel.getProperty("/data/" + i + "/question")
    			};
    			oCurrentQuestionModel.setProperty("/", oCurrent);
    			this.byId("questionText").setText(oCurrentQuestionModel.getProperty("/question"));
    		}
    	});
    
    
    });
    
     
    Add comment
    10|10000 characters needed characters exceeded