I have an App not develloped in Sapui5 at all. But I loke the Grid Table and its option, therefore I integrate it into an Div dedicaced for it.
This is my Code:
sap.ui.getCore().attachInit(function () {
sap.ui.require([
], function () {
new sap.ui.xmlview({
viewName : "sap.ui.demo.cart.view.DcpTable"
}).placeAt("vueAppSales");
})
}
);
I injected this div with Ajax.
When i leave this page and i come back to this page, the same code was launched another time and the xmlview was duplicate.
How can i handle that to test if the element is create or not to duplicate the view?
Thanks
you can give an id to your view and after that you can check if your view was created already or not
sap.ui.getCore().attachInit(function () {
sap.ui.require([
], function () {
var myView = sap.ui.getCore().byId('myView')
if(!myView){
myView = new sap.ui.xmlview({
id: 'myView'
viewName : "sap.ui.demo.cart.view.DcpTable"
})
}
myView.placeAt("vueAppSales");
})
}
);
but its only a guess
Related
Im new to backbone and I'm looking to a very simple 2 view configuration page usig backbone.
I have the following code;
define(
["backbone","...","..."],
function(Backbone, ... , ... ) {
var PopupView = Backbone.View.extend({
initialize: function initialize() {
Backbone.View.prototype.initialize.apply(this,arguments);
},
events: {
"click .save_conf_button": "save_conf",
},
render: function() {
this.el.innerHTML = this.get_popup_template();
return this;
},
save:conf: function save_conf() {
//get the field values from popup_template
//var items = jquery(....);
});
var ExampleView = Backbone.View.extend({
//Starting view
initialize: function initialize() {
Backbone.View.prototype.initialize.apply(this, arguments);
},
events: {
"click .setup_button": "trigger_setup", //Triggers final setup
"click .create_conf_button": "trigger_popup_setup", //This is the conf popup
},
render: function() {
this.el.innerHTML = this.get_start_html();
return this;
},
trigger_popup_setup: function trigger_popup_setup() {
console.log("Pop up");
//this.el.innerHTML = this.get_popup_template();
PopupView.render();
...
},
}); //End of exampleView
return ExampleView;
} // end of require asynch
); // end of require
E.g. The ExampleView is the starting view with a couple of fields and 2 buttons; create popup and save. Upon pressing the create_conf_button I want to render the popup view, however this does not seem to work as I expected. (Uncaught TypeError: PopupView.render is not a function)
I'm not sure how to proceed and additionally what the "best practice" is for generating these types of dialogs?
Additionally, keeping the values filled in on the previous page after returning from the popupview would be preferential.
Thanks for any help
try
new PopupView.render()
you have to create an instance to call the methods this way
#ashish is correct, you have to instantiate an instance of the PopupView before calling its render method. Currently, you have defined a blueprint for a view called PopupView, which will act as a constructor for newly created PopupView view instances. In order to use this defined view I would suggest storing it in ExampleView's render or initialize method:
// Example View's initialize method
initialize: function initialize() {
this.popUpView = new PopupView();
Backbone.View.prototype.initialize.apply(this, arguments);
},
then referencing it in your trigger_popup_setup function as follows:
trigger_popup_setup: function trigger_popup_setup() {
console.log("Pop up");
//this.el.innerHTML = this.get_popup_template();
this.popUpView.render();
...
},
As for storing state Backbone models are used for that :)
In general to nest subviews within a master view in Backbone you can do the following:
initialize : function () {
//...
},
render : function () {
this.$el.empty();
this.innerView1 = new Subview({options});
this.innerView2 = new Subview({options});
this.$('.inner-view-container')
.append(this.innerView1.el)
.append(this.innerView2.el);
}
In this example the master view is creating instances of it's subviews within its render method and attaching them to a corresponding DOM element.
I have the shell view that contains the navbar and the map. To this view is rendered other views that use the map previous rendered. When I'll go to the view perfil the map is removed, but the navbar is maintained, so far so good. My problem is when turn back to the home, the map doesn't appear only appears the div that contains the map. Bellow show the example:
View Shell and view Home:
go to view Perfil:
turn back to home:
heres my code:
app.js
var ev = new Application();
ev.Router = Backbone.Router.extend({
routes: {
"": "home",
"evento/:id" : "evento",
"criarevento" : "criarevento",
"perfil" : "perfil"
},
home: function(){
setTimeout(function(){
$('#rightcolumn').html(new ev.views.Home(ev.shell.map).el);
}, 0);
},
... // other views
perfil: function(){
setTimeout(function(){
$('#home').html(new ev.views.Perfil(ev.shell.template).el);
}, 0);
}
});
$(document).on('ready', function() {
ev.user = new ev.models.Person(); // Holds the authenticated Facebook user
// Load HTML templates for the app
ev.templateLoader.load(['shell', 'home', 'search_keyword', 'evento', 'login', 'quemvai', 'criar_evento', 'home_criar_evento', 'perfil'], function () {
ev.shell = new ev.views.Shell({el: "#shell", model: ev.user});
ev.router = new ev.Router();
Backbone.history.start();
});
});
perfil.js
ev.views.Perfil = Backbone.View.extend({
initialize: function(temp, model){
var that = this;
that.template = _.template(ev.templateLoader.get('perfil'));
that.template2 = temp;
//console.log(this.view);
ev.router.on("route", function(route, params) {
that.$el.html(that.template2());
});
that.render();
},
render: function(map){
this.$el.html(this.template());
return this;
}
});
So far I created an event that when route changes, the shell template that I step to the view perfil is called. But it's not working. What I'm doing wrong?
EDITS:
I change my constructor in view perfil, so that when route changes only fire once and call the render function of ev.shell
ev.views.Perfil = Backbone.View.extend({
initialize: function(){
var that = this;
that.template = _.template(ev.templateLoader.get('perfil'));
ev.router.once("route", function(route, params) {
ev.shell.render();
});
that.render();
},
render: function(map){
this.$el.html(this.template());
return this;
}
});
It looks like you have a document ready even that loads the shell including the map. When you go to the profile page you replace the contents of the #home element. Then when you go back to home you replace the contents of the #rightcolumn element. You never re-render the map.
I think you need to put the map rendering code into the home function of the router as well.
As a side note I noticed you are using setTimeout function. If you are using this so that something renders because it's waiting on something else to load then you should probably get rid of it and listen to an event.
OK, I've done some reading on this and I'm pretty sure I know what the problem relates to I Just don't know the best way to fix it. I've got the standard backbone router that sets me up with an item details view, then when I click on a button called "start" it creates a new view which takes me to a sort of a game that people can play with some buttons on the bottom that have "click" events attached. This second view is not called through the router but directly from the first view.
The problem is the second time someones goes back to the homescreen and does it again, this time there are two events attached to each button. The third time there are three events. Obviously the original views are still listening to these buttons. I've read about this and calling the Remove() method but is this what I need to do? If so where do I call remove? Relevant Code below:
1ST VIEW
window.GameDrillView = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
$(this.el).html(this.template(this.model.toJSON()));
return this;
},
events: {
"click .start" : "startGameDrill",
},
startGameDrill: function () {
var start = $('#start').val();.
var stop = $('#stop').val();.
var StartView = new GameDrillStartView({model: this.model, el: $('#content')[0], start: start, stop:stop});
}
});
START VIEW
window.GameDrillStartView = Backbone.View.extend({
// declare variables
initialize: function () {
this.render();
},
events: {
"click .nextstage" : "nextstage", // 2ND TIME THROUGH GETS CALLED TWICE
},
nextstage: function () {
// Do some stuff //
this.render(); //Re-render
},
render: function () {
// Do some variables stuff
this.$el.html(this.template(jQuery.extend(this.model.toJSON(), extended_options)));..
return this;
}
});
When changing view you need to call undelegateEvents() method from the Backbone.View. It disable listening all the elements events mentioned in events { } block. Also if you need to destroy old view you can call remove() method of the view which will call undelegateEvents() internally.
update (example from official site)
var Workspace = Backbone.Router.extend({
routes: {
"help": "help", // #help
"search/:query": "search", // #search/kiwis
"search/:query/p:page": "search" // #search/kiwis/p7
},
help: function() {
if (this.currentView)
this.currentView.undelegateEvents();
this.currentView = new HelpView();
},
search: function(query, page) {
if (this.currentView)
this.currentView.undelegateEvents();
this.currentView = new SearchView();
}
});
An option is to create only one instance of the view:
if(_.isUndefined(this.StartView))
this.StartView = new GameDrillStartView({model: this.model, el: $('#content')[0], start: start, stop:stop});
else
this.StartView.render();
In the render method of GameDrillStartView add the empty method
this.$el.html(this.template(jQuery.extend(this.model.toJSON(), extended_options)))
In this way you won't add more event listeners but you'll update the page everytime the user presses the button.
You can manage the life cycle of StartView in GameDrillView since it seems like a better place to do so.
Got same trouble. Messy solution:
var current_view = false;
var prev_view = false;
var AppRouter = Backbone.Router.extend({
routes: {
"events/:id": "viewEvent",
}
});
var app_router = new AppRouter;
app_router.on('route:viewEvent', function (event_id) {
var _event = new Event({id:event_id});
current_view = new EventView({
model: _event,
});
});
//Will be called after route:viewEvent
app_router.on('route', function () {
if(prev_view) {
prev_view.undelegateEvents();
}
prev_view = current_view;
});
Not sure, how to make it without having current_view and prev_view out of router scope.
I have this strange issue where a view doesn't show up when I go to the page. However, if I refresh the page, it'll appear.
In my router, I tried to render 2 views like so:
tags: function(tags) {
self = this;
self.multipleTags = tags.split('/');
self.tagsArray = $.grep(self.multipleTags, function(item,index) {
return (item != '');
});
var browseHeader = new BrowseHeader;
var content = new tagsView({query:self.tagsArray});
},
I'm having trouble with my BrowseHeader though but the tagsView works fine. I did try removing my tagsView to see if maybe they were conflicting. However, even with a single view rendering, the header still wouldn't show up until I refresh the page.
Here is what I'm doing in my BrowseHeader view:
var browseHeader = Backbone.View.extend({
initialize: function() {
this.render();
},
template: function() {
dust.render('dust/browseHeader','', function(error, output) {
$('#wrapper').append(output);
});
},
render: function() {
this.template();
},
el: '#wrapper',
events: {
'click .academy_filter' : "click_filter"
},
click_filter: function(event) {
target = event.target;
$('.academy_filter').removeClass('active');
$(target).addClass('active');
EventBus.trigger('header:click_filter', target);
}
});
When I console.log the output, it does display the html for the output despite it not being shown on the page. So I know my dust template is working. When I simplify my BrowseHeader render function to just $('#wrapper').append("this"); I still experience the same issue.
Any ideas?
Update: Apparently it has something to do with browser and pushState because when I changed my router to the following, it worked fine.
Backbone.history.start({pushState: true});
As far as I can tell, there's nothing wrong with your view. This is most likely a timing issue. Your view is probably being initialized (and therefore rendered) before #wrapper exists in the DOM. My guess is that if you try the following, the output will be 0:
dust.render('dust/browseHeader','', function(error, output) {
console.log($('#wrapper').length);
$('#wrapper').append(output);
});
Make sure the view is being created after the DOM has finished loading, like so:
$(document).ready(function() {
var header = new browseHeader();
});
I'm developing admin panel to my website and decided to do it with knockout and sammy. But I am faced with a routing problem. I have two pages:
http://localhost/admin/element and http://localhost/admin/category.
On my element page I have the following Sammy config:
Sammy(function() {
this.get('#:currentpage', function() {
self.reloadPage(this.params.currentpage);
});
this.get('', function() {
this.app.runRoute('get', '#1');
});
}).run();
Everything works perfect but if I try to go to another page (by usual link, e.g. Edit Categories) I just get to the empty route on the same page, so I just cannot go to another page with link. Any ideas how to fix that?
Don't use '' in your Sammy configuration. Try '/' for root page or '/admin/element' for your elements instead.
var Router = function() {
var sammy = new Sammy.Application(function() {
this.get('#:currentpage', function(context) {
alert(context.params.currentpage);
});
this.get('/admin/element', function () {
this.app.runRoute('get', '#1');
});
}),
run = function() {
sammy.run();
};
return {
run: run
};
};
$(function() {
var r = new Router();
r.run();
});
PS: The example uses version of Sammy 0.7.1. In version 0.6.3 there is another behavior.
This works if you have an action link and want to click through to another page
`<li>#Html.ActionLink("Admin Action Link Test", "Admin", "Home")</li>
this.get('/Home/Admin', function ()
{
location.assign("/Home/Admin");
});`
or you can do this using the hash
<li>About Full Path</li>
this.get('#/Home/About', function ()
{
location.assign("/Home/About");
});