How to dynamically bind an existing OpenUI5 Combobox? - sapui5

I'm evaluating OpenUI5 and I'm not clear about the binding concept.
In a XML login view, I have a Combobox that I want to populate after a successful login:
<ComboBox id="cboJoraniInstance" enabled="false" />
So, into my controller I've created an Ajax call with a parameter:
return Controller.extend("sap.ui.jorani.wt.controller.Login", {
onCheckEmail : function () {
var oDialog = this.getView().byId("BusyDialog");
oDialog.open();
var sMail = this.getView().byId("txtEmail").getValue();
var oListInst = this.getView().byId("cboJoraniInstance");
var aData = jQuery.ajax({
type : 'POST',
url : 'http://localhost/dummy/getJoraniInstances.php',
data: {
mail: sMail
},
async: false,
success : function(data,textStatus, jqXHR) {
//Link Combobox
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
oListInst.setModel(oModel);
oListInst.bindElement("/Instances");
oListInst.bindProperty("value", "Url");
oListInst.bindProperty("name", "name");
oListInst.setEnabled();
},
error: function (jqXHR, textStatus, errorThrown){
MessageToast.show('An error occured');
}
});
oDialog.close();
},
});
The call to my web service is OK and returns:
{
"Instances": [{
"Name": "Local",
"IsDefault": true,
"Url": "http:\/\/localhost\/jorani\/"
}, {
"Name": "D\u00e9mo",
"IsDefault": false,
"Url": "https:\/\/demo.jorani.org\/"
}]
}
The code executes without error, but the control is not filled by my binding attempts.
I've checked the various SO questions on this topic and they all add a new ComboBox into the view dynamically, for example:
oListInst.placeAt("content");
But that is not what I want to achieve, I'd like to fill an existing object. Is it possible?
Concerning the view, if I fill the Combobox with the code below, it is working fine (but it doesn't use the binding feature):
$.each(data.Instances, function(i, obj) {
oListInst.addItem(new sap.ui.core.ListItem({key:obj.Url, text:obj.Name}));
});

Related

Unable to access control, created in JSView, from controller with View byId

I am trying to display a VizFrame and my data are in a simple JSON format.
Both my view and controller are in JS. (I will start writing my view in XML going forward) because I see that is the way to go.
I get a blank page with the error: "setDataset of undefined". What am I missing?
My view code is this.
createContent: function(oController) {
var oSubHeader = new sap.m.Bar({
contentLeft: [
new sap.m.Button({
icon: "sap-icon://nav-back",
press: [oController.onNavBack, oController]
})
],
contentMiddle: [
new sap.m.Label({
text: "{i18n>app_subhead_2}"
})
]
});
var oVizFrame = new sap.viz.ui5.controls.VizFrame("VizFrameId", {
width: "100%",
height: "400px",
vizType: "line"
});
var oPage = new sap.m.Page({
title: "UI5 Assignment App",
showSubHeader: true,
subHeader: oSubHeader,
content: [oVizFrame]
});
return oPage;
}
My corresponding controller is
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/UIComponent",
"sap/ui/core/routing/History",
"sap/viz/ui5/controls/VizFrame",
"sap/viz/ui5/data/FlattenedDataset"
], function (Controller, UIComponent, History, VizFrame, FlattenedDataset) {
"use strict";
return Controller.extend("Project_Tile_learning.Divya_tile_Project.controller.ProductDetailPage", {
onNavBack: function () {
var oHistory = History.getInstance();
var sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("homepage", true);
}
},
onInit: function () {
var sampleDatajson = new sap.ui.model.json.JSONModel("json/PA.json");
var oVizFrame = this.getView().byId("VizFrameId");
var oDataset = new sap.viz.ui5.data.FlattenedDataset({
dimensions: [{
name: "Year",
value: "{Year}"
}],
measures: [{
name: "Supplier",
value: "{Supplier}"
}, {
name: "Liquor",
value: "{Liquor}"
}, {
name: "Quantity",
value: "{Quantity}"
}],
data: {
path: "/items"
}
});
oVizFrame.setDataset(oDataset);
oVizFrame.setModel(sampleDatajson);
var oFeedValueAxis = new sap.viz.ui5.controls.common.feeds.FeedItem({
"uid": "valueAxis",
"type": "Measure",
"values": ["Supplier"]
});
var oFeedValueAxis1 = new sap.viz.ui5.controls.common.feeds.FeedItem({
"uid": "valueAxis",
"type": "Measure",
"values": ["Liquor"]
});
var oFeedValueAxis2 = new sap.viz.ui5.controls.common.feeds.FeedItem({
"uid": "valueAxis",
"type": "Measure",
"values": ["Quantity"]
});
var oFeedCategoryAxis = new sap.viz.ui5.controls.common.feeds.FeedItem({
"uid": "categoryAxis",
"type": "Dimension",
"values": ["Year"]
});
oVizFrame.addFeed(oFeedValueAxis);
oVizFrame.addFeed(oFeedValueAxis1);
oVizFrame.addFeed(oFeedValueAxis2);
oVizFrame.addFeed(oFeedCategoryAxis);
}
});
});
Update: JS View is deprecated since UI5 v1.90. Use Typed View instead.
When creating a control in JS view definition, always use this.createId("myControl").
From the doc:
If you want to define IDs for controls inside a JSView to guarantee their uniqueness [...], you cannot give hardcoded IDs, but have to give the view the opportunity to add its own instance ID as a prefix. This is done by using the View.createId(...) method.
For the example above, this is done as follows:
new sap.viz.ui5.controls.VizFrame(this.createId("VizFrameId"), { /*...*/ });
Then in the controller, myView.byId tries to access the control with view's own ID as a prefix, which will succeed this time since the control has an ID with the view ID as a prefix.

jsTree: with lazy loading the plugin "dnd" is not working

I'm using jsTree (latest version) in my web app. I have a lot of nodes to display in the tree, so I am using lazy loading otherwise I would run into a time out.
When the tree is loaded, the user can pick values from a second tree and move them into the lazy loaded tree (jsTree plugin "dnd"). Both tree have the jsTree plugin "dnd" installed. But I can not drop a element into the lazy loaded tree, when I try to do so the node to be dropped is having an icon with a red cross (indication: not allowed here).
This is the code for the lazy loaded tree:
$('#target_tree').jstree({
'core' : {
'data' : {
"url" : "get_current_hierachy",
"data" : function (node) {
return {'p_parent_id': node.id};
},
"dataType": "json",
"check_callback": true
}
},
"plugins" : ["dnd"]
});
When I load some data in the first tree without the lazy loading, the drag'n'drop is working as expected.
When I load data in the first tree with lazy loading, the drag'n'drop is not working any more.
Any help would be greatly appreciated.
Try this ...
$(document).ready(function () {
$('#target_tree').jstree({
'core': {
'data': {
"url": function (node) {
var url;
if (node.id == '#') {
url = "getRootNode";
} else {
var id = $(node).data("id");
url = "getChildNode?nodeid=" + id;
}
return url;
},
"data": function (node) {
return { "id": node.id };
},
"type": "GET",
"dataType": "json",
"contentType": "application/json charset=utf-8",
},
'check_callback': true,
},
"plugins": ["dnd"]
});
});
I think you need to prepare url

How to create knockout datagrid on popup from within datagrid

I have a datagrid that has additional information I'd like to show in a pop up.
I display an icon to alert the user this information exists. The icon has a click action that performs a callback to the server to get this information. When I click this, I have all my data ready to view, but am not sure of the MVVM logistics of this.
Here is a mockup of what I'm trying to do. The alert function displays a modal popup. The click handler works, and the callback works fine.
I'm wondering, where do I create the new grid model, should it be a part of the current grid model, where do I apply bindings?
var initialData = [
{ name: "ABC", number: 1, icon: true},
{ name: "DEF", number: 2, icon: false },
];
var GridModel = function(items) {
this.items = ko.observableArray(items);
this.gridViewModel = new ko.simpleGrid.viewModel({
data: this.items,
columns: [
{ headerText: "Name", rowText: "name" },
{ headerText: "Number", rowText: "number" },
{ headerText: "Addl Info",
rowText: function (item)
{
return item.icon ? "<i class=\"icon\"></i>" : "";
},
clickHandler: function (item)
{
function callback(data) {
// data is now an array of objects I want a data grid for that displays in the pop up.
alert("Additional Information", <HTML GOES HERE>);
}
$$.getJSON("url", [], callback);
}
],
});
};
ko.applyBindings(new GridModel(initialData));

How do I pass a JSON object from one controller to another(/view to view)?

I want to pass a JSON object from one controller to another. How do I do that?
Or can I pass a oModel to the other view? If so how do I do that?
Thanks
If you store your data in a global model:
var oData = <your JSON data>;
var oModel = new sap.ui.model.json.JSONModel(oData);
sap.ui.getCore().setModel(oModel);
it can then be accessed from any other controller/view in your application context
one solution is that you use sap.ui.core.EventBus. Basically you can pass any object from one controller to another including JSONModel using subscribe and publish.
To add to Qualiture's answer:
If you wanted to attach a specific model to a specific view, which your question sounds like a little, you can do just that by going:
view.setModel(oModel);
Cheers
Michel
yes,you can pass string,object and Array from one view to another through the Navigation.
enter code here
enter code here for controller
handleLinkPress: function(oEvent) {
try {
var array = [];
var obj = {
"Delivery": "80000095",
"DelvNo": "80000095",
"Date": "2018-01-04T00:00:00.000Z",
"Priority": "00",
"LoadDate": "2018-01-04T00:00:00.000Z",
"PickDate": "2018-01-04T00:00:00.000Z",
"ShippingPoint": "0001",
"Route": "",
"LoadingPoint": "01",
"ShipTo": "CUSTOMER",
"SoldTo": "CUSTOMER"
};
array.push(obj);
if (obj !== null) {
sap.ui.core.UIComponent.getRouterFor(this).navTo("Route", {
RouteData: JSON.stringify(array)
});
}
} catch (e) {
console.error("Error : " + e.message);
sap.m.MessageBox.show(e.message, {
icon: sap.m.MessageBox.Icon.ERROR,
title: "Error",
actions: [sap.m.MessageBox.Action.OK],
defaultAction: sap.m.MessageBox.Action.OK,
styleClass: "sapUiSizeCompact",
contentWidth: "150px"
});
}
}
Code for manifest.json
{
"pattern": "Route/{RouteData}",
"name": "Route",
"targetControl": "masterView",
"viewId": "Route",
"viewName": "Route"
}
code for the controller where you get that Array which you want pass
handleCloseRoutePress: function(oEv)
{
var sRouteData=JSON.parse(oEv.getParameter("arguments").RouteData);
}

Saving nested collections within a model using backbone.js

I am having some issues getting Backbone to save multiple layers of collections. I have the following models:
var Question = Backbone.Model.extend({
urlRoot: "/question"
});
var QuestionList = Backbone.Collection.extend({
model: Question,
url: "/question",
parse: function(response) {
return response.objects;
}
});
var QuestionBank = Backbone.Model.extend({
urlRoot: "/questionbank"
});
var QuestionBankList = Backbone.Collection.extend({
model:QuestionBank,
url: "/questionbank",
parse: function(response) {
return response.objects;
}
});
var Answer = Backbone.Model.extend({
urlRoot: "/answer"
})
var AnswerList = Backbone.Collection.extend({
model: Answer,
url: "/answer",
parse: function(response) {
return response.objects;
}
});
A questionbank has many questions, and a question has many answers.
When I save my collection the model is correct, but the JSON that is sent out does not include the second level of collection (the answers):
{"active_question_bank": true, "id":
"51a8c5d72ace7a458fd0d000", "question_bank_name": "New Q", "questions":
[{"active_question": true, "answers": [], "difficulty": null,
"id": "51a8d1be2ace7a458fd0d008", "question": "What is your favorite Color?",
"question_is_and_type": false, "question_type": 1, "resource_uri":
"/question/51a8d1be2ace7a458fd0d008", "tags": [""]}], "resource_uri":
"/questionbank/51a8c5d72ace7a458fd0d000"}
In particular it sends a blank "answers": [] every time. I'm relatively new to backbone, so perhaps this is an impossible task, but the concept seems fairly trivial.
Try defining the models and collections in the following pattern and then check the JSON being sent to the server.
var Answer = Backbone.Model.extend({
urlRoot: "/answer",
});
var AnswerCollection = Backbone.Collection.extend({
model: Answer,
urlRoot: "/answer",
});
// a question can contain many answers which can be accessed via AnswerList
var Question = Backbone.Model.extend({
urlRoot: "/question",
defaults: {
AnswerList: new AnswerCollection(),
},
parse: function(response) {
response.AnswerList= new AnswerCollection(response.AnswerList);
return response;
}
});
var QuestionCollection = Backbone.Collection.extend({
model: Question,
url: "/question",
});
// question-bank contains many questions which can be accessed via QuestionList
var QuestionBank = Backbone.Model.extend({
urlRoot: "/questionbank",
defaults: {
QuestionList: new QuestionCollection(),
},
parse: function(response) {
response.QuestionList = new QuestionCollection(response.QuestionList);
return response;
}
});