how to get view references in SAPUI5? - javascript

Let's say I have my routes defined in my manifest.json like this
rootView: "sap.ui.core.sample.TargetsStandalone.targetsApp.view.App",
routing: {
config: {
targetsClass: "sap.m.routing.Targets",
viewPath: "sap.ui.core.sample.TargetsStandalone.targetsApp.view",
controlId: "rootControl",
controlAggregation: "pages",
viewType: "XML"
},
targets: {
page1: {
viewName: "View1",
viewLevel: 0
},
page2: {
viewName: "View2",
viewLevel: 1
}
}
}
Is there a way to retrieve the view references from the component(getOwnerComponent). What I want to do is, on the first controller I want to get a reference of label on "View2". It seems like there is no reference to the second view until I navigate to it. Is there a way to get the a reference to another view and its elements before I navigate to it?

When you navigate to a view, the runtime instantiate it. Before that, there is no view. You can even see in the network trace how the XML file of certain view is downloaded once you navigate to it for the first time, but not before.

Related

Prevent view invalidation when route changes in SAPUI5

I have a page with a route #grants/{grantId} that contains tabbed content. I want each tab to be accessible by route #grants/{grantId}/{tabId}.
So I've setup router like below and i works, however when I switch tabs (e.g. when i go from #grants/123/tab1 to #gratns/123/tab2) the conent of the page gets rebuild (invalidated). How can I prevent that?
var oRouter = new sap.ui.core.routing.Router([
{
pattern: "grants",
name: "_grants",
view: "grants.Grants",
viewType: sap.ui.core.mvc.ViewType.HTML,
viewId: "grants",
targetControl: "theContent",
targetAggregation: "content",
clearTarget: true,
subroutes: [
{
pattern: "grants/{id}/:period:",
name: "_grantPortfolio",
view: "grants.GrantPortfolio",
viewType: sap.ui.core.mvc.ViewType.HTML,
viewId: "grantPortfolio",
targetControl: "theContent",
targetAggregation: "content",
clearTarget: true
}]
}]);
As far as I understand your question I would suggest to implement a special logic in your controller's route match callback. There you can check - depending on the event parameter - which data needs to be loaded and which data have been loaded already. For more specific hints a running example would be required.

How to use Backbone's trigger method

I have this Backbone App where users and admins can log in and out. Now admins do have multiple options to add features on different pages, so for that, I have an admin-menu which should only display the relevant buttons on the relevant page. I want to use the trigger-method but cant get it working properly. So lets say, admins should have the possibility to change something on the frontpage, so a specific button should be visible, only on when navigating to the frontpage. This is what I did so far:
Router.js:
routes: {
'': 'index',
'home': 'home'
}
home: function(){
App.trigger('showFrontBtn');
}
Then on my Admin-MenuView.js:
Admin-Menu.View = Backbone.View.extend({
tagName: 'div',
template: 'adminMneu',
initialize: function() {
this.render();
App.on('showFrontBtn', this.changeFront, this);
},
changeFront:function(user){
alert('works!')
if(user && user.role === 'admin'){
$('.frontBtn').show();
} else {
$('.frontBtn').hide();
}
},
The thing is, that it actually returns the alert('works'), so I assume there must be an issue with the if statement, BUT am I using the method correctly?
The function changeFront:function(user) is expecting a "user" object passed into it. But when you triggered the event, you didn't specify the parameter to pass (user).
I am guessing when you tried to access "user.role" it threw an exception because user is null and you are trying to get to null.role.
You might be confusing the third argument of the event listener with the parameter of the function. The third parameter of the app.on is actually the context not the parameter. The parameter needs to be passed by the trigger. So you can do something like
home: function(){
App.trigger('showFrontBtn', {role: "Admin"});
}

Enyo MVC implementation and particle view rendering

Could you please help me with MVC implementation with enyojs framework
The current goal is to implement N -panels (displays, windows) for TV application which would be changed after button was pressed (channel switch for instance). It looks just like simple redirect to new URL (or controller's action) in web. So, we want to re-render views and parts of views and update windows(panels) using strategy of keeping just 2 displays at the same time (current and next we go with animation). I learned some examples of MVC with enyo from other topics here, but that implementations of MVC but some questions are still exist.
Problem: how to implement in enyo the particle updating of the view with new data from controller ?
//--- app.js
enyo.kind({
name: "my.Application",
kind: "enyo.Application",
view: "Index", // default start view
controllers: [ // I use 2.3 version and know about this rudiment property.
{name: "homeController", kind: "HomeController"}
],
viewChanged : function() {
this.inherited(arguments);
app.render(); // this updates the view. Changes from index to edit and back.
}
});
enyo.ready(function () {
app = new my.Application({name: "app"});
});
//------ controller.js + IndexView.js + editview.JS
enyo.kind({
name : "IndexView",
kind: "enyo.View",
components: [
{content: "HelloWorld, This is Index"},
{content: "This is the Index view"},
{kind: "moon.ToggleButton", content: "Show Edit", ontap: "buttonTapped"}
],
// redirect to Edit View
buttonTapped: function(sender, event){
app.controllers.homeController.Edit("message(model) to Edit View");
}
});
enyo.kind({
name : "EditView",
kind: "enyo.View",
message: "no msg",
components: [
{name: "headWithId", content: "Hello! This is EDIT."},
{content: "This is the Edit view"},
{kind: "moon.ToggleButton", content: "Show Index", ontap: "buttonTapped"}
],
bindings: [
{from: ".message", to:".$.headWithId.content"}
],
// redirect to Index View
buttonTapped: function(sender, event){
app.controllers.homeController.Index();
}
});
enyo.kind({
name : "HomeController",
kind: "enyo.Controller",
Index : function(){
app.set("view", new IndexView()); // this code updates the view of app, but maybe there is a better way to do it?
},
Edit : function(msg){
app.set("view", new EditView({message: msg}));
}
});
The previous code works find. There some question in comments. But how to implement such situation, then I don't want to rerender all the divs of the view, but just particle content (for example, leave the header and update the content):
// ----- baselayoutview.js
enyo.kind({
name : "BaseLayout",
kind: "enyo.ViewController", // or enyo.View... what is better?
components: [
{content: "this content of the View never changes"},
// next content should be changed. It's for renderTarget
{name: "RenderContentSection"} // How to render new content form Index or Edit view here?
]
});
// ----- app.js
enyo.kind({
name: "my.Application",
kind: "enyo.Application",
view: "BaseLayout", // We set this base layout view and expect the it will fill it's content by itself
controllers: [
{name: "homeController", kind: "HomeController"}
],
viewChanged : function() {
this.inherited(arguments);
app.render("RenderContentSection"); // I think it would not be working any more.. but what it the best way to do it? How to update BaseLayout view's RenderContentSection ?
}
});
You should not be calling app.render() to re-render your application. As you say, you don't want to re-render the whole thing each time. Are you stuck on Enyo 2.3 or can you update to a more recent version? Controllers have been largely deprecated, for one.
I suggest taking a look at the Panels component. You can place a Panels component within your area that changes and navigate to a panel and push whatever content you want into that panel. You individual sections would be Panel components and you can push and pop those as needed. If you need to replace the panel.
If you really want to do it that way, you can modify your BaseLayout component so that it uses createComponent() to create whichever partial view you want.
enyo.kind({
name : "BaseLayout",
// This can be just a plain enyo.Control
components: [
{content: "this content of the View never changes"},
// next content should be changed. It's for renderTarget
{name: "renderContentSection"} // How to render new content form Index or Edit view here?
],
replacePartial: function(partial) {
this.$.renderContentSection.destroyClientControls();
this.$.renderContentSection.createComponent({kind: partial});
this.$.renderContentSection.render();
}
});
Here's a fiddle showing that off: http://jsfiddle.net/RoySutton/LhjLv6hy/
You could create a new control with a 'chrome' controls and a client area that controls get rendered into, but this is pretty simple. Still, take a look at Panels. It's what they were designed for.

call a view from controller in secha touch MVC pattern

I want to render a view which I create when the button on another view is clicked.
Here is my controller code, and I am following the MVC architecture
Ext.define('demo.controller.LoginController' , {
extend: 'Ext.app.Controller',
config: {
refs:{
loginAction: 'button[action=login]'
},
control:{
loginAction: {
tap:'loginProcess'
}
}
},
loginProcess:function(button,e,opts){
// Render View here
}
});
I have searched and I came across getMainView().push() and Ext.ViewPoart.add() but it's not working. According to the MVC pattern how should call this view from a controller?
EDIT
code of profilecontainer
Ext.define('demo.view.ProfileContainer',{
extend:'Ext.Panel',
xtype:'profilecontainer',
requires: [
'Ext.Label'
],
config: {
items:[{
xtype:'label',
html:'hi'
}]
}
});
Both of the ways you have tried should work, if you set them up correctly.
First, getMainView().push(newView) will work if mainView is an Ext.navigation.View. See the docs for this method here: http://docs.sencha.com/touch/2.2.1/#!/api/Ext.navigation.View-method-push
You can also use Ext.Viewport.setActiveItem(newView), assuming you have no typos (your post says ViewPoart). (Ext.Viewport.add will add the panel to the Viewport, but not set it as the active Card in the layout)
If neither of these are working, then you probably are not configuring your controller correctly. If that is the case, ensure that your loginProcess method is being called. If it is not, then your selector, button[action=login], is not correct.

Sencha Touch 2 Global Variables - Access everywhere

I know this question was already posted in StackOverflow but I either didnt understand or sencha changed somewhat.
My app loads a form panel for login, then I would like to save the user info that have just loged on. This way I can change my view anytime I want and still know the name of the loged in user.
Here is my main code:
//<debug>
Ext.Loader.setPath({
'Ext': 'sdk/src'
});
//</debug>
Ext.application({
name: 'APP',
loadedUser: 'the test',
requires: ['Ext.MessageBox'],
views: ['Main', 'Home', 'Login'],
models: ['User'],
stores: ['Users'],
controllers: ['Main'],
icon: {
57: 'resources/icons/Icon.png',
72: 'resources/icons/Icon~ipad.png',
114: 'resources/icons/Icon#2x.png',
144: 'resources/icons/Icon~ipad#2x.png'
},
phoneStartupScreen: 'resources/loading/Homescreen.jpg',
tabletStartupScreen: 'resources/loading/Homescreen~ipad.jpg',
setLoadedUser: function(arg) {
this.loadedUser = arg;
},
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
Ext.Viewport.add(Ext.create('APP.view.Main'));
},
onUpdated: function() {
Ext.Msg.confirm("Application Update", "This application has just successfully been updated to the latest version. Reload now?", function() {
window.location.reload();
});
}
});
The 'loadedUser' its what I wanted to be my global variable, and the method setLoadedUser(arg) its suposed to change that value.
I can access 'loadedUser' no problem, but I can't change its value.
Another question: loadedUser can it be an array/data structure?
How are you accessing the function? This works for me. Remember you should access it like this:
APP.app.setLoadedUser('test');
And yes, it can be any value. :)
You can also use localStorage to, set/get Your variables:
Set it as:
localStorage.setItem('currentUserId', userID)
Get it as:
localStorage.getItem('currentUserId')
You can use it, anywhere in Your script.
Yes, the works when the function is inside of the app.js file.
It does not work if the function is inside of the controller file.
So if you have a project application called IronMan, the call from the view code to the global function, flyAway(), in your app.js file would look like:
IronMan.app.flyAway();

Categories