Recentemente eu tive um pouco de contato com algumas ferramentas dessa nova onda de produtos SAP e resolvi dividir um pouco dessa experiência nesse blog. Vou mostrar como desenvolver uma aplicação UI5 utilizando os conceitos do SAP Fiori, nessa aplicação iremos consumir os dados via “oData” direto do Hana. Antes de mais nada precisamos entender do que se trata essas ferramentas e tecnologia citadas anteriormente no contexto desse blog.
Bom não vou contar a história de cada ferramenta ou tecnologia utilizada para desenvolver essa aplicação, até porque o foco desse blog não e esse, irei apenas dar uma pequena definição sobre cada uma delas.
"SAP UI5" com poucas palavras pode ser definido como sendo uma biblioteca Java script da SAP para criação de aplicações baseadas em HTML5.
"SAP FIORI" e focado na experiência do usuário – 01:01:03 (Um caso de uso, um usuário, três telas) e tem pequenos aplicativos combinados. Tem uma variedade de aplicações que falam a mesma língua, que privilegia o design de informação.
"SAP HANA" Podemos pensar no Hana como um pen drive gigante, que armazena só as informações mais relevantes aquelas mais utilizadas, recorrentes, o Hana e uma plataforma cuja combinação de software in-memory e hardware proporciona ao usuario a consulta de múltiplos tipos de origens de dados em tempo real.
"oData" é, na verdade, um serviço que contém uma classe que oferece um conjunto de informações para quem quiser consumir.
Conhecendo um pouco sobre cada uma das ferramentas e tecnologias vamos ao desenvolvimento. Vale a pena citar que estou colocando o oData, as tabelas, tudo no projeto principal por uma questão de simplicidade. Antes de mais nada, vamos abrir nosso ambiente de desenvolvimento, utilizaremos o Eclipse Luna.
Vamos abrir o Eclipse (Hana Studio) e criar um novo projeto clicando em File -> New -> Other -> Application Project.
Agora iremos dar um nome em nossa aplicação, reparem que existe um campo que se chama "Library" e dois checkedboxes, que são o "sap.ui.commons" que nada mais é que um conjunto de controles de interface gráfica próprios para desktops e o “sap.ui.m” que são um conjunto de controles de interface gráfica próprios para dispositivos móveis, em nossa aplicação vamos escolher o recurso para desenvolvimento desktop e prosseguir clicando em "Next".
Vamos escolher o projeto e em seguida definir um nome, logo abaixo escolheremos a opção Java Script, porém é possível de se utilizar também “xml”, “JSON” e “HTML”, bom fazendo isso vamos finalizar a criação de nosso projeto clicando em “Finish”.
Com nossa estrutura do projeto criada iremos primeiro criar nossas tabelas no Hana, para isso clique com o botão direito em Web Content -> New Folder e definir o nome para o diretório de “tables”.
Dentro do diretório que acabamos de criar com o botão direito escolha a opção New -> Data Base Developer-> DDL Source File.
Logo em seguida defina um nome em nosso arquivo com a extensão "hdbdd".
Vamos agora abrir o arquivo “funcionário.hdbdd” e criar nossas tabelas conforme mostra o trecho de código a seguir.
namespace tmp.guilherme.appfiori.WebContent.tables;
@Schema: 'GUILHERME'
context func {
type ty_id_cidade: hana.VARCHAR(1);
type ty_id_cargo: hana.VARCHAR(2);
type ty_funcionario: hana.VARCHAR(2);
type ty_descricao: hana.VARCHAR(800);
@Catalog.tableType: #COLUMN
entity cidades {
key id_cidade : ty_id_cidade;
ds: ty_descricao;
};
@Catalog.tableType: #COLUMN
entity cargos {
key id_cargo : ty_id_cargo;
cidade: association to func.cidades;
ds: ty_descricao;
};
@Catalog.tableType: #COLUMN
entity funcionarios {
key id_funcionario : ty_funcionario;
cargo : association to func.cargos;
name: hana.VARCHAR(100);
image: hana.VARCHAR(300);
title: hana.VARCHAR(400);
ds: ty_descricao;
};
};
Bom, iremos subir nossa aplicação para o servidor no Hana, clicando no projeto em Team -> Share Project.
E preciso definir um diretório para nossa aplicação, para isso clicamos em browser, logo em seguida clicamos em "Finish".
Subimos nossa aplicação para o servidor no Hana, nossas tabelas estão criadas agora e preciso criar um "oData" para consumir ela, para isso devemos clicar com o botão direito em Web Content e clicar em New -> Folder e definir um nome em nosso "oData".
Então agora, dentro desse diretório recém-criado com o botão direito clique em New -> XS Odata File e definir um nome para ele.
Vamos agora abrir o arquivo “funcionarios.xsodata” e colocar o seguinte trecho de código para criação do oData.
service namespace "br.com.duxinnovation.appfiori"
{
association "Cidade_Cargo"
principal "Cidades"("id_cidade") multiplicity "1"
dependent "Cargos"("cidade.id_cidade") multiplicity "*";
association "Cargo_Funcionario"
principal "Cargos"("id_cargo") multiplicity "1"
dependent "Funcionarios"("cargo.id_cargo") multiplicity "*";
"tmp.guilherme.appfiori.WebContent.tables::func.cidades" as "Cidades"
navigates ("Cidade_Cargo" as "Cargos")
create forbidden
update forbidden
delete forbidden
;
"tmp.guilherme.appfiori.WebContent.tables::func.cargos" as "Cargos"
navigates ("Cargo_Funcionario" as "Funcionarios")
create forbidden
update forbidden
delete forbidden
;
"tmp.guilherme.appfiori.WebContent.tables::func.funcionarios" as "Funcionarios"
create forbidden
update forbidden
delete forbidden
;
}
Acabamos de criar o "oData" de nossa aplicação, iremos agora ativar nosso projeto para que possamos testar o serviço “oData”.
Vamos executar o “oData” já consumindo alguns dados no Hana, teremos o seguinte resultado.
Pronto, já estamos com as tabelas criadas e com carga, o serviço “oData” está apto a consumir os dados da aplicação. Agora é necessário implementar o “oData” em nossa aplicação UI5. Dentro do diretório “WebContent” vamos criar alguns arquivos, primeiramente é necessário se criar um diretório que podemos definir como “diretorio_appfiori”.
Dentro desse diretório devemos criar dois arquivos que serão nossa página inicial de nossa aplicação, podemos definir o nome de “Welcome.view.js ”. Dentro dele definiremos o seguinte trecho de código.
sap.ui.jsview("appfiori.Welcome", {
/** Specifies the Controller belonging to this View.
/** In the case that it is not implemented, or that "null" is returned.
/** @memberOf appfiori.Welcome
getControllerName : function() {
return "appfiori.Welcome";
},
/** Is initially called once after the Controller has been instantiated.
/** Since the Controller is given to this method.
/ ** @memberOf appfiori.Welcome
createContent : function(oController) {
var oImage = new sap.m.Image({
src: "resources/home_.jpg",
width: '760px'
});
var oText = new sap.m.Text({
text: ""
}).addStyleClass('welcomeText');
return new sap.m.Page({
title: "Bem Vindo a Lista de Funcionarios da Empresa X",
content: [
new sap.m.VBox({
items: [oImage,oText],
alignItems: sap.m.FlexAlignItems.Center,
justifyContent: sap.m.FlexJustifyContent.Center
})
]
});
}
Então agora crie um arquivo “Welcome.controller.js”, abra o arquivo e implementar o seguinte trecho de código.
sap.ui.controller("appfiori.Welcome",
{
});
Em seguida criaremos um “js” para Cidade, que iremos definir o nome de “Cidade.controler.js” e definir o seguinte trecho de código.
sap.ui.controller("appfiori.Cidade", {
* @memberOf appfiori.App
cidadeListItemPress: function(evt) {
var router = sap.ui.core.UIComponent.getRouterFor(this);
var context = evt.getSource().getBindingContext('funcionarios');
var path = context.sPath;
var start = path.indexOf("'") + 1;
var end = path.lastIndexOf("'");
var cidIndex = path.substring(start, end);
var modnav = sap.ui.getCore().byId("app").getModel("nav");
modnav.setProperty("/cid",cidIndex);
router.navTo('cidade', {cidIndex: cidIndex});
}
});
Logo em seguida vamos criar o arquivo “Cidade.view.js” com o seguinte trecho de código:
sap.ui.jsview("appfiori.Cidade", {
/** Specifies the Controller belonging to this View.
/** In the case that it is not implemented, or that "null" is returned.
/** @memberOf appfiori.Cidades
getControllerName : function() {
return "appfiori.Cidade";
},
/** @memberOf appfiori.Cidade
createContent : function(oController) {
var oList = new sap.m.List({
id: "listId"
});
oList.bindItems({
path : "funcionarios>/Cidades",
template : new sap.m.StandardListItem({
title: "{funcionarios>ds}",
type: sap.m.ListType.Navigation,
press:function(evt){
oController.cidadeListItemPress(evt);
}
})
});
return new sap.m.Page({ title: "Cidades",
content: [oList]
});
});
Acabamos de codificar o controller e a view de “Cidade”, o próximo passo e fazer o mesmo para Cargo de onde e associado a uma cidade. Vamos criar um novo arquivo “Cargo.view.js” e usar o seguinte código em sua estrutura.
sap.ui.jsview("appfiori.Cargos", {
/** Specifies the Controller belonging to this View.
/** In the case that it is not implemented, or that "null" is returned.
/** @memberOf appfiori.Cargos
getControllerName : function() {
return "appfiori.Cargos";
},
* @memberOf appfiori.Cargos
*/
createContent : function(oController) {
var oList = new sap.m.List({
id: "slistId",
mode: sap.m.ListMode.SingleSelect,
select: function(evt) {
oController.itemSelect(evt);
}
});
return new sap.m.Page({
title: "Cargos",
showNavButton: true,
navButtonPress: function() {
oController.goBack();
},
});
}
});
Logo em seguida criaremos o “Cargos.controller.js” e usaremos o seguinte trecho de código.
sap.ui.controller("appfiori.Cargos", {
/** @memberOf appfiori.Cargos
onInit: function() {
this.router = sap.ui.core.UIComponent.getRouterFor(this);
this.router.attachRoutePatternMatched(this._handleRouteMatched, this);
},
_handleRouteMatched: function(evt) {
if("cidades" !== evt.getParameter("name"))
{
return;
}
this.cidadeIndex = evt.getParameter("arguments").cidadeIndex;
this.cargoIndex = evt.getParameter("arguments").cargoIndex;
var modnav = sap.ui.getCore().byId("app").getModel("nav");
var cidIndex = modnav.getProperty("/cid");
var list = sap.ui.getCore().byId('slistId');
list.bindItems({
path: "funcionarios>/Cidades('" + cidIndex + "')/Cargos",
template: new sap.m.StandardListItem({
title: "{funcionarios>ds}"
})
});
},
itemSelect: function(evt) {
var list = sap.ui.getCore().byId('slistId');
var sItem = list.getSelectedItem();
var oBindingContext = sItem.getBindingContext('funcionarios');
var sPath = oBindingContext.sPath;
var start_subcat = sPath.indexOf("'") + 1;
var end_subcat = sPath.lastIndexOf("'");
var subCatIndex = sPath.substring(start_subcat, end_subcat);
var modnav = sap.ui.getCore().byId("app").getModel("nav");
modnav.setProperty("/cargo",cargoIndex);
this.router.navTo("Funcionarios", {cidIndex:
this.cidIndex, cargotIndex: cargoIndex});
},
goBack: function() {
this.router.navTo("");
}
});
Agora iremos criar mais dois arquivos para funcionário. Primeiro vamos criar o “Funcionario.view.js” com o seguinte trecho de código:
sap.ui.jsview("appfiori.Funcionarios", {
/** Specifies the Controller belonging to this View.
/** In the case that it is not implemented, or that "null" is returned.
* @memberOf appfiori.Funcionarios
*/
getControllerName : function() {
return "appfiori.Funcionarios";
},
/** Is initially called once after the Controller has been instantiated.
/** Since the Controller is given to this method.
* @memberOf appfiori.Funcionarios
*/
createContent : function(oController) {
var oTable = new sap.m.Table("funcionariosTable",{
inset: true,
columns: [
new sap.m.Column({
hAlign: "Left",
width: "100px",
demandPopin: true,
popinDisplay: "Block",
minScreenWidth: sap.m.ScreenSize.Medium
}),
new sap.m.Column({
hAlign: "Left",
demandPopin: true,
popinDisplay: "Block",
minScreenWidth: sap.m.ScreenSize.Medium
}),
new sap.m.Column({
hAlign: "Left",
width: "100px",
demandPopin: true,
popinDisplay: "Block",
minScreenWidth: sap.m.ScreenSize.Medium }),
new sap.m.Column({
hAlign: "Left",
width: "100px",
demandPopin: true,
popinDisplay: "Block",
minScreenWidth: sap.m.ScreenSize.Medium
})
]
});
return new sap.m.Page({
title: “",
content: [oTable]
});
}
});
Iremos criar o “Funcionarios.controller.js” com o seguinte trecho de código.
sap.ui.controller("appfiori.Funcionarios", {
* @memberOf appfiori.Funcionario
*/
onInit: function() {
this.router = sap.ui.core.UIComponent.getRouterFor(this);
this.router.attachRoutePatternMatched(this._handleRouteMatched, this);
},
_handleRouteMatched: function(evt) {
if("Funcionarios" !== evt.getParameter("name")){
return;
}
this.cidIndex = evt.getParameter("arguments").cidIndex;
this.cargoIndex = evt.getParameter("arguments").cargoIndex;
var modnav = sap.ui.getCore().byId("app").getModel("nav");
var cidIndex = modnav.getProperty("/cid");
var cargoIndex = modnav.getProperty("/cargo");
var oTemplate = new sap.m.ColumnListItem({
type: sap.m.ListType.Active,
cells: [
new sap.m.Image({
src: "{funcionarios>image}",
height: "100px"
}),
new sap.m.Text({
text: "{funcionarios>name} \n {funcionarios >title}"
}
]
});
oTemplate.attachPress(function(evt) {
this.funcionarioPress(evt);
},this);
sap.ui.getCore().byId("funcionariosTable")
.bindAggregation(
"funcionarios>" +
"/Cidade('" + cidIndex + "')"+
"/Cargo('" + cargoIndex + "')" +
"/Funcionarios",
oTemplate
);
},
funcionarioPress: function(oEvent) {
var oBindingContext = oEvent.getSource().getBindingContext('funcionarios');
var sPath = oBindingContext.sPath;
var start = sPath.indexOf("'") + 1;
var end = sPath.lastIndexOf("'");
var funcionarioIndex = sPath.substring(start, end);
var modnav = sap.ui.getCore().byId("app").getModel("nav");
modnav.setProperty("/func",funcionarioIndex);
}
});
Vamos acessar nosso diretório principal e criar um arquivo “Component.js” e codificar da seguinte maneira.
sap.ui.core.UIComponent.extend("sap.demo.Component",{
metadata: {
routing: {
config: {
viewType: "JS",
viewPath: "diretorio_appfiori",
targetControl: "splitApp",
clearTarget: false,
transition: "slide"
},
routes: [ {
pattern: "cidade/{cidIndex}",
name: "cidade",
view: "Cargo",
targetAggregation: "masterPages",
subroutes:[{
pattern: "cidade/{cidIndex}/cargo/{cargoIndex}",
name: "Funcionarios",
view: "Funcionarios",
targetAggregation: "detailPages" },]
},
{
pattern: "",
name: "default",
view: "Cidade",
targetAggregation: "masterPages",
subroutes: [
{
pattern: "",
name: "Welcome",
view: "Welcome",
targetAggregation: "detailPages"
}
]
},
init: function() {
jQuery.sap.require("sap.m.routing.RouteMatchedHandler");
jQuery.sap.require("sap.ui.core.routing.HashChanger");
//call createContent
sap.ui.core.UIComponent.prototype.init.apply(this, arguments);
this._router = this.getRouter();
this._routeHandler = new sap.m.routing.RouteMatchedHandler(this._router);
this._router.initialize();
},
createContent: function() {
var oView = sap.ui.view({
id: "app",
viewName: "appfiori.App",
type: "JS",
viewData: {component: this}
});
var oModeldata = new sap.ui.model.odata.ODataModel ("/tmp/guilherme/WebContent/oData/funcionarios");
oView.setModel(oModeldata,"funcionarios");
Bom, agora falta somente codificar o “index.html” que vai ficar da seguinte maneira.
<!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="/sap/ui5/1/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.m"
data-sap-ui-xx-bindingSyntax = "complex"
data-sap-ui-resourceroots = '{
"appfiori": "./appfiori",
"sap.demo": "./"
}'
data-sap-ui-theme="sap_bluecrystal">
</script>
<!-- only load the mobile lib "sap.m" and the "sap_bluecrystal" theme -->
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>
Bom, terminamos nossa aplicação, se tudo correr certo o resultado final será o seguinte.
Tela inicial da aplicação com as opções de selecionar a cidade e em seguida o cargo.
Tela de listagem de funcionários cadastrados em determinado cargo de determinada cidade.
Bom pessoal, espero que tenham gostado desse artigo, tentei ser o mais claro possível e levantar as principais dúvidas que eu também encontrei na criação de minhas primeiras aplicações, bom desenvolvimento a todos e até a próxima.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
6 | |
4 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 | |
3 | |
3 |