I am new to SAPUI5/OPENUI5.
I am trying out a sample program to consume json data from a domain and display it in my openui5 table. I have tried two methods to get the data and bind it to table control.But I am not able to generate the table with the json data.
Please let me know my mistake in the code.
And also please refer me some links to understand the concept in a better way.
Thanks in advance.
Please find the two approaches below :
JSON Data :
[
{
"name": "Rajesh"
},
{
"name": "Kunal Jauhari"
},
{
"name": "Ashish Singh"
},
{
"name": "Ansuman Parhi"
},
{
"name": "Arup Kumar"
},
{
"name": "Deepak Malviya"
},
{
"name": "Seshu"
},
{
"name": "Ankush Datey"
},
{
"name": "Tapesh Syawaria"
},
{
"name": "Mahesh"
},
{
"name": "Vinay Joshi"
},
{
"name": "Ardhendu Karna"
},
{
"name": "Abhishek Shukla"
},
{
"name": "Kashim"
},
{
"name": "Vinayak"
}
]
Approach 1 : I am using a php file to echo the JSON data and use it in my ui5 screen.
When I access the run the php file individually, it generates the data and prints the data on screen.
Error I get is getJSON is not called.
Code :
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.ui.commons,sap.ui.table"
data-sap-ui-theme="sap_bluecrystal">
</script>
<!-- add sap.ui.table,sap.ui.ux3 and/or other libraries to 'data-sap-ui-libs' if required -->
<script>
var json_url = "http://mydomain/teamdetails_ui5.php?t=6";
$.ajax({
url : json_url,
jsonpCallback : 'getJSON',
contentType : "application/json",
dataType: 'jsonp',
success: function(data,textStatus,jqXHR) {
oModel.setData({data: data});
sap.ui.getCore().setModel(oModel);
var oTable1 = new sap.ui.table.Table({
title : "Players List",
visibleRowCount : 3,
selectionMode : sap.ui.table.SelectionMode.Single,
navigationMode : sap.ui.table.NavigationMode.Paginator,
});
//Define the columns and the control templates to be used
oTable1.addColumn(new sap.ui.table.Column({
label : new sap.ui.commons.Label({
text : "Player Name"
}),
template : new sap.ui.commons.TextView().bindProperty(
"text", "name"),
width : "10px"
}));
oTable1.setModel(oModel);
oTable1.bindRows("/oModel");
oTable1.placeAt('table_cont');
},
error : function(jqXHR,textStatus,errorThrown) {
alert("Oh no, an error occurred");
alert(jqXHR);
alert(textStatus);
alert(errorThrown);
}
});
</script>
</head>
<body class="sapUiBody" role="application">
<div id="table_cont"></div>
</body>
</html>
Approach 2 : I am trying to access the JSON file directly on my domain and access the data.
Code is the same as above except url.
Url is used for this approach is (mydomain/players.json) where players.json contain the above json data.
Please help me in understanding the concept of JSON data handling.
Regards,
Rajan
First of all: SAPUI5 is built onto jQuery, yes. But there should be no need to use jQuery inside your SAPUI5 Application.
Use a JSONModel to load JSON-Data. Also the JSONModel can load the data from URL.
See the Documentation
this will look like:
// create a "json" Model
var oModel = new sap.ui.model.json.JSONModel();
// load data from URL
oModel.loadData('http://mydomain/teamdetails_ui5.php?t=6');
after this you can register this model in your sap.ui.core with:
sap.ui.getCore().setModel(oModel);
after this line every control can use the data from this model by simple binding-syntax.
Now lets create the table:
// create your table
var oTable1 = new sap.ui.table.Table({
title : "Players List",
visibleRowCount : 3,
selectionMode : sap.ui.table.SelectionMode.Single,
navigationMode : sap.ui.table.NavigationMode.Paginator,
// bind the core-model to this table by aggregating player-Array
rows: '{/player}'
});
beware of the part with "rows: '{/player}'". This is the only thing that has to be done to get the data from the model inside your table.
now finish the demo by adding the column and add the table to the DOM:
// define the columns and the control templates to be used
oTable1.addColumn(new sap.ui.table.Column({
label : new sap.ui.commons.Label({
text : "Player Name"
}),
template : new sap.ui.commons.TextView({
text: '{name}'
}),
width : "10px"
}));
//place at DOM
oTable1.placeAt('content');
Thats it. If it doesn't work, here is a running DEMO.
Related
I am a total javascript/leaflet/ag-grid newbie, so please bear with me.
I am creating a website that allows users to query (add/remove) spatial points on a leaflet map based on selecting rows from ag-grid. I have no understanding/experience with React or Angular, so I am using vanilla javascript. Leaflet is used to display the data spatially.
I have spatial data that has GPS coordinates that are parent records. Each parent they have multiple children.
Spatial data
The spatial data is an external file I read into my HTML file. It looks like this:
var spatial_data = {
"type": "FeatureCollection",
"features": [
{ "type": "Feature",
"properties": { "Name": "Boulder 1", "SpatialID": "Lower Blair_0" },
"geometry": { "type": "Point", "coordinates": [ -105.39079766, 41.19044516, 2510.159912109375 ] } },
{ "type": "Feature",
"properties": { "Name": "Boulder 2", "SpatialID": "Upper Blair_1" },
"geometry": { "type": "Point", "coordinates": [ -105.39058423, 41.19655902, 2534.4599609375 ] } }
]};
Children records
There are children records for each parent spatial ID. The data is within the .js code.
The functionality I am hoping for is someone could filter the ag-grid for a route called 'Slam Dunk' and that would provide the "SpatialID":"Lower Blair_0". If they filter for 'Test two' it provides the same SpatialID. This would be available to play around within the HTML file.
myownscript.js
var rowData = [{"Route Name":"Slam Dunk","SpatialID":"Lower Blair_0"},
{"Route Name":"Test two","SpatialID":"Lower Blair_0"},
{"Route Name":"Test three","SpatialID":"Upper Blair_1"}];
var columnDefs= [
{field: 'Route Name', minWidth:10, sortable:true, filter:true},
{field: 'Sub-Area', minWidth:5, sortable:true, filter:true},
];
const gridOptions = {
columnDefs: columnDefs,
rowData: rowData,
defaultColDef:{
flex:1,
minWidth:100
},
rowSelection: 'multiple',
pagination:true
};
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
};
function grabFilteredData(){
let rowData = [];
gridOptions.api.forEachNodeAfterFilter(node => {
rowData.push(node.data.SpatialID);
});
var uniqueID = rowData.filter(onlyUnique);
return uniqueID;
}
document.addEventListener('DOMContentLoaded', () => {
const gridDiv = document.querySelector('#myGrid');
new agGrid.Grid(gridDiv, gridOptions);
});
I can easily send 'test' to the console. That provides me with the ability to check that my onSelectionChanged() is working; however, I really need to pass the output from onSelectionChanged() as an array. I need to pass that and use that in an embedded script within my HTML. This is so I can filter the data in my leaflet layers and features.
my html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Read in the geojson-->
<script src='assets/spatialdata.json'></script>
<script src="https://unpkg.com/ag-grid-community#27.0.1/dist/ag-grid-community.min.js"></script>
<script src="myownscript.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="bstrap/js/bootstrap.min.js"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.10.1/bootstrap-table.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/ag-grid-community/dist/styles/ag-grid.css">
<link rel="stylesheet" href="https://unpkg.com/ag-grid-community/dist/styles/ag-theme-alpine.css">
</head>
<body>
<script >
var sat_data = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © OpenStreetMap contributors, Imagery © Mapbox',
maxZoom: 18,
id: 'mapbox/satellite-streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: 'my.api.key'
});
var bounds = new L.LatLngBounds(new L.LatLng(41.008,-106.710), new L.LatLng(41.813,-104.861));
var baseMaps = {
"Satellite":sat_data
};
var map = L.map('map', {
center: [41.210, -105.360],
zoom: 11,
layers:[osm,sat_data],
noWrap:true,
maxBounds:bounds,
maxBoundsViscosit:1.0
});
L.control.layers(baseMaps).addTo(map);
var promise = $.getJSON("/assets/vedauwoo.geojson");
promise.then(function(data){
var allData = L.geoJson(data,{
onEachFeature: function(feature,layer){
layer.bindPopup('<h4> Area Name: '+feature.properties.Name+'</h4><p>Grades: '+feature.properties.Grade+'</p>');
}
});
var others = L.geoJson(data, {
onEachFeature: function(feature,layer){
layer.bindPopup('<h4> Area Name: '+feature.properties.Name+'</h4><p>Grades: '+feature.properties.Grade+'</p>');
},
filter: function(feature,layer){
}
});
var layerGroup = L.layerGroup().addTo(map);
allData.addTo(layerGroup)
$("#others").click(function() {
var dataToSubset = grabFilteredData();
var subset_data = L.geoJson(data, {
onEachFeature: function(feature,layer){
layer.bindPopup('<h4> Area Name: '+feature.properties.Name+'</h4><p>Grades: '+feature.properties.Grade+'</p>');
},
filter: function(feature,layer){
return dataToSubset.includes(feature.properties.SpatialID);
}
});
//Works in a hacky way by sending the ID over
layerGroup.removeLayer(allData)
layerGroup.addLayer(subset_data)
window.map_id = subset_data._leaflet_id;
});
$("#allData").click(function() {
layerGroup.removeLayer(map_id)
layerGroup.addLayer(allData)
});
</script>
</body>
</html>
I have tried extensive searching. For some reason, the majority of use cases for gridOptions.api.getSelectedRows() or forEachNodeAfterFilter end with an example of using console.log(). I need to actually pass that information along instead of just outputting to the console. I am not sure if this is a misunderstanding on my part for how JS works, or if it is expected behavior from ag-grid, but it doesn't seem possible.
This doesn't seem to work as the console.log() in the .js file doesn't work, and in the script in the HTML it can not find test.
I am primarily a statistician/python programmer, so this a new foray for me. It is likely I am missing a bigger picture thing and if so, I would appreciate alternatives to my current approach.
So once onSelectionChanged is called with the filtered rows - what script do you need to pass it to?
I assume you want to link the table with the leaflet map. If so, you need to
obtain a reference to the map object (see Leaflet docs)
create a GeoJSON layer based on the filtered Geometries and add it to the map.
If the filtering in the table and thus the leaflet layer data update happens multiple times, you need to remove the existing layer and add a new one, as far as I know. Check this post.
$('#placeSelect').select2({
width: '100%',
allowClear: true,
multiple: true,
maximumSelectionSize: 1,
placeholder: "Click here and start typing to search.",
data: function(query) {
queryData{!randomJsIden}(query);
},
matcher: function (term, text) {if (text.toUpperCase().indexOf(term.toUpperCase()) == 0){return true;}return false;}
});
function queryData{!randomJsIden}(query){
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.AutoCompleteV2_Con.getData}','{!sObjVal}','{!labelFieldVar}','{!valueFieldVar}',query.term,
function(result, event){
//if success
if(event.status){
var data = {results:[{ id: 1, text: "Ford" },
{ id: 2, text: "Dodge" },
{ id: 3, text: "Mercedes" },
{ id: 4, text: "Jaguar" }]}
query.callback( data);
}
},
{escape: true}
);
}
</script>
How to initialize query call back data to data attribute in select2 .
I cannot use data directly .In above example i am using sample data .
query : function(query){
queryData{!randomJsIden}(query);
}
I want to replace this by data attribute like this : the below one is not working
data : function(query){
queryData{!randomJsIden}(query);
}
here is the fiddle :
http://jsfiddle.net/Lnf8j/303/
Let me know any ideas from you
There are couple of issues in your code
you cannot name a function using flower braces as it is reserved notation symbol in javascript function queryData{!randomJsIden}(query), instead name it as function queryData(query){ ... }
if your adding a callback for data of your select2 then you need to return that data constructed from queryData() function.
data: function(query) {
return queryData(query);
},
function queryData(query){
...
return data;
}
If i'am not wrong,data is sourced to select2 via asynchronous call inside queryData(), which means the data is returned at unpredictable time,so you need to restrict the user from accessing the select2 component until data is feeded to it.
which means you either need to prefetch the data or disable the select2 field until data is returned from remote call.
Working Demo # JSFiddle
Using gmap3 (a jquery plugin) to display a Google maps interface. I'm trying to load my data from a JSON file but for some reason it's not executing. The map displays, the addMarkers() function is being called, but if I put a console.log() anywhere inside function(data), it doesn't display.
I'm somewhat confused about these anonymous functions and haven't worked with asynchronous functions before. Any advice would be much appreciated.
Javascript
$(document).ready(function(){
displayMap();
addMarkers();
});
// Create map with options
function displayMap(){
$('#map_canvas').gmap3({
map: {
options: mapOptions
}
});
};
// Load data and add markers for each data point
function addMarkers(){
$.getJSON( dataURL, function(data) {
$.each( data.markers, function(i, marker) {
console.log( marker.lat + ':' + marker.lng + ':' + marker.data.category + ':' + marker.data.content );
})
});
};
JSON
{
markers: [
{ lat:-30, lng:145, data: {title: "Le Restaurant", category:"Restaurant", content:"Some French restaurant"} },
{ lat:-30, lng:145, data: {title :"Gem Cafe", category:"Cafe", content:"They sell coffee"} },
{ lat:-30, lng:145, data: {title :"Home", category:"Home", content:"Home sweet home."} }
]
}
Silly me, just checked my JSON format using http://jsonlint.com/ and discovered it was malformed. I needed to enclose the 'key' names in quotes like so ...
{
"markers": [
{ "lat":-30, "lng":145, "data": {"title": "Le Restaurant", "category":"Restaurant", "content":"Some French restaurant"} },
{ "lat":-30, "lng":145, "data": {"title" :"Gem Cafe", "category":"Cafe", "content":"They sell coffee"} },
{ "lat":-30, "lng":145, "data": {"title" :"Home", "category":"Home", "content":"Home sweet home."} }
]
}
I can't find this anywhere and i don't know why the cross domain REST request is not solved by dojo. anyways here is the problem:
I am implementing dojo data-grid, and i am trying to get the data for the grid from a WCF that is not in my domain, so i crossdomain problem is raised and i am trying to over come this problem by using JSONP.
but i am a newbie in dojo so i am probably doing something wrong. here is my code:
require([
"dojo/store/JsonRest",
"dojo/store/Memory",
"dojo/store/Cache",
"dojox/grid/DataGrid",
"dojo/data/ObjectStore",
"dojo/query",
"dijit/form/Button",
"dojo/domReady!",
"dojo/request/script","dojo/dom-construct"
],function(script, domConstruct){
//make the request just as before
script.get("http://localhost:8060/ListService.svc/LoadLists?uid=c4446476-15e6-e111-9ecb-b7c5971d170a", {
jsonp: "callback",
query: {q: "#dojo"}
}).then(function(data){
test = data;
}).then(function(){
console.log(results);
});
}, function (JsonRest, Memory, Cache, DataGrid, ObjectStore ,query) {
grid = new DataGrid({
store: dataStore = test,
structure: [
{ name: "Blog Id", field: "id", width: "50px", },
{ name: "Name", field: "listtype", width: "200px",classes:"Name" },
{ name: "Phone Number", field: "longlevel", width: "200px",classes:"test" }
]
}, "gridTest"); // make sure you have a target HTML element with this id
grid.startup();
dojo.query("body").addClass("claro");
grid.canSort = function () { return false; };
});
the error i am getting is query is not a function. any ideas how to implement this correctly.
Simple mistake just put the data grid command inside the first then with the data returning
require([
"dojo/store/JsonRest",
"dojo/store/Memory",
"dojo/store/Cache",
"dojox/grid/DataGrid",
"dojo/data/ObjectStore",
"dojo/query",
"dijit/form/Button",
"dojo/domReady!",
"dojo/request/script","dojo/dom-construct"
],function(script, domConstruct){
//make the request just as before
script.get("http://localhost:8060/ListService.svc/LoadLists?uid=c4446476-15e6-e111-9ecb-b7c5971d170a", {
jsonp: "callback",
query: {q: "#dojo"}
}).then(function(data){
function (JsonRest, Memory, Cache, DataGrid, ObjectStore ,query) {
grid = new DataGrid({
store: dataStore = test,
structure: [
{ name: "Blog Id", field: "id", width: "50px", },
{ name: "Name", field: "listtype", width: "200px",classes:"Name" },
{ name: "Phone Number", field: "longlevel", width: "200px",classes:"test" }
]
}, "gridTest"); // make sure you have a target HTML element with this id
grid.startup();
dojo.query("body").addClass("claro");
grid.canSort = function () { return false; };
})
}).then(function(){
console.log(results);
});
};
If you still find a problem probably because the grid is created before the request is returning from the wcf.
if that happened please use the Deferred in dojo 1.8 which make you in control of you processes sequence.
so you will be able to call the request give it some time and then put the data in the grid to be viewed.
I'm trying to construct a solid Backbone JS experiment, where I have a local JSON data file which contains my pages (a project I'm doing has this sort of requirement anyhow). And I've coded this example so I can have endless nested subpages in the pages data. It seems to be working great. But when it comes to the URLs, I'm a little stuck.
How do I approach giving this multiple level navigation example totally dynamic URLs? What I mean is, correctly using the url property of the models and collections to construct the right URLs for all the top level and nested elements. Is it even possible? I just can't think how to do it.
See a live demo of where I am now:
http://littlejim.co.uk/code/backbone/multiple-level-navigation-experiment/
Just so it's easier, the source code is below...
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Multiple Level Navigation Experiment</title>
<script type="text/javascript" src="../../media/scripts/jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="../../media/scripts/underscore-min.js"></script>
<script type="text/javascript" src="../../media/scripts/backbone-min.js"></script>
<script type="text/javascript" src="application.js"></script>
<script type="text/javascript">
// wait for the DOM to load
$(document).ready(function() {
App.initialize();
});
</script>
</head>
<body>
<div id="header">
<h1>Multiple Level Navigation Experiment</h1>
<p>Want to get this page structure pulled from JSON locally and have a fully functional multiple level nested navigation with correct anchors.</p>
</div>
<div id="article">
<!-- dynamic content here -->
</div>
</body>
</html>
content.json
{
"pages": [
{
"id": 1,
"title": "Home",
"slug": "home"
},
{
"id": 2,
"title": "Services",
"slug": "services",
"subpages": [
{
"id": 1,
"title": "Details",
"slug": "details",
"subpages": [
{
"id": 1,
"title": "This",
"slug": "this"
},
{
"id": 2,
"title": "That",
"slug": "that"
}
]
},
{
"id": 2,
"title": "Honest Service",
"slug": "honest-service"
},
{
"id": 3,
"title": "What We Do",
"slug": "what-we-do"
}
]
},
{
"id": 3,
"title": "Contact Us",
"slug": "contact-us"
}
]
}
application.js
// global app class
window.App = {
Data: {},
Controller: {},
Model: {},
Collection: {},
View: {},
initialize : function () {
$.ajax({
url: "data/content.json",
dataType: "json",
success: function(json) {
App.Data.Pages = json.pages;
new App.Controller.Main();
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(errorThrown);
}
});
}
}
// main controller class
// when called it should have 'data' in JSON format passed to it
App.Controller.Main = Backbone.Controller.extend({
initialize: function() {
var pagesCollection = new App.Collection.Pages(App.Data.Pages);
var pagesView = new App.View.Pages({collection: pagesCollection});
$('#article').html(pagesView.render().el);
}
});
// pages model class
App.Model.Page = Backbone.Model.extend({
initialize: function() {
if (!_.isUndefined(this.get("subpages"))) {
this.subpages = new App.Collection.Pages(this.get("subpages"));
} // end if
this.view = new App.View.Page({model: this});
},
});
// page collection class
App.Collection.Pages = Backbone.Collection.extend({
model: App.Model.Page
});
// single page view class
App.View.Page = Backbone.View.extend({
tagName: "li",
initialize: function() {
_.bindAll(this, "render");
},
render: function() {
$(this.el).html(_.template("<%=title%>", {title: this.model.get("title")}));
return this;
}
});
// multiple pages view class
App.View.Pages = Backbone.View.extend({
tagName: "ul",
initialize: function() {
_.bindAll(this, "render");
},
render: function() {
var that = this;
this.collection.each(function(page) {
$(that.el).append(page.view.render().el);
if (!_.isUndefined(page.subpages)) {
var subpagesView = new App.View.Pages({collection: page.subpages});
$(that.el).append(subpagesView.render().el);
} // end if
});
return that;
}
});
I'm just needing so right direction on how to do the URLs properly. The idea I'm wanting is that I can setup my controller for routes so it can expect any page of any nested level. The models, collections and nested collections should be able to generate their URLs on their own, but the hash URL must reflect the level.
Ideally, this navigation would go to URLs like these:
http://example.com/#pages/services
http://example.com/#pages/services/details
http://example.com/#pages/services/details/this
...the URLs using the "slug" from the content.json data. Does any of this make sense? I'm pretty new to Backbone JS and just want to do things right.
Thanks, James
Here's my favorite solution to this problem: use PathJS !
Why not just parse out the slug?
So you can have a single route in the Backbone.Controller that looks like this:
'pages/:id' : showPage
And then showPage looks like:
showPage(id) : function(id) {
parse out the string 'services/details/etc'
look up the slug data based on that IE pages['services']['details']['etc']
}
or if the pages actually need to be processed differently, you can setup multiple routes, ever more granular like this:
'pages/:id' : showPage
'pages/:id/:nest' : showNestedPage
'pages/:id/:nest/:more' : showNestedMorePage