How can I programmatically change the current location ?
The app-location is on parent element and I want change it from the child element.
here is parent excerpt
dom-module(id='test', assetpath='/')
template
app-location(route='{{route}}')
app-route(route='{{route}}', pattern='/:page', data='{{rootData}}', tail='{{rootTail}}')
...
login-page(name='login', route='[[rootTail]]')
...
script.
Polymer({is: 'test');
and the child
dom-module(id='login-page')
template
div(class='layout horizontal center-justified mh400')
div(class='layout vertical center-justified')
form(is='iron-form', id='login-form', method='post', action='/api/auth/login', on-iron-form-response='onResponse')
...
script.
Polymer({
is: 'login-page',
onResponse: function (event) {
var resp = event.detail.response;
if (resp.success) {
// Change here the location
}
}
})
Sorry by the Jade instead of html but give to understand i think.
app-location simply interfaces with the location bar of the browser. It uses iron-location internally. There's nothing stopping you from including it in the child element as well. It's role here would be to update the location bar (instead of listening to changes). In your JavaScript, select the element and update its path.
The app-location in the parent element will detect the change in the location bar and update route
dom-module(id='login-page')
template
app-location
div(class='layout horizontal center-justified mh400')
div(class='layout vertical center-justified')
form(is='iron-form', id='login-form', method='post', action='/api/auth/login', on-iron-form-response='onResponse')
...
script.
Polymer({
is: 'login-page',
onResponse: function (event) {
var resp = event.detail.response;
if (resp.success) {
// TODO: Update with your new path
this.shadowRoot.querySelector('app-location').path = '';
}
}
})
Related
For Angular ui-tree, i want to add expland all or collapse all.
I tried the following code and it works.
$scope.collapseAll = function () {
$scope.$broadcast('angular-ui-tree:collapse-all');
};
$scope.expandAll = function () {
$scope.$broadcast('angular-ui-tree:expand-all');
};
...
The question is,my page have multiple ui tree, i only want to trigger expandAll function for separate. now i trigger this expandAll function. ALL ui -tree will be affected.
Is there any solution to set each one as seperate?
How to call collapseAll function on Angular UI tree?
If you check at the Source of angular ui tree , the 'angular-ui-tree:collapse-all' event toggles a scope value . Other problem being each of the directives in angular-ui-tree inherits the scope of the parent than having a isolated scope . So changing the when you broadcast an event it is actually changing the same scope value .
You should either find a way for each tree's to have a separate scope or think of using some other tree's like v-accordion .
we should broadcast angular-ui-tree:collapse-all for specified tree scope.
It's work for me.you can use it without any hesitation at all.
function collapseAll() {
var treeScope = _getRootNodesScope('myTreeId');
if (treeScope) {
treeScope.$broadcast('angular-ui-tree:collapse-all');
}
}
function expandAll() {
var treeScope = _getRootNodesScope('userTreeroot');
if (treeScope) {
treeScope.$broadcast('angular-ui-tree:expand-all');
}
}
function _getRootNodesScope(myTreeId) {
var treeElement = angular.element(document.getElementById(myTreeId));
if (treeElement) {
var treeScope = (typeof treeElement.scope === 'function') ?
treeElement.scope() : undefined;
return treeScope;
}
return undefined;
};
In my website, in order to load diferent pages (to be multipage website) I have a main panel that has the id 'content-panel'.
When I want to load a diferent page I have a javascript function that is called 'loadPage' that loads the page (panel) that I want to the 'content-panel'.
But the page that I want to load has to have this code:
Ext.require(['*']);
Ext.onReady(function() {
...
var panel = Ext.Cmp('content-panel');
panel.add(loginPanel);
panel.layout.setActiveItem(loginPanel);
panel.doLayout();
panel.setLoading(false);
});
In this case it is loading the page/panel that is loginPanel, that is defined inside Ext.onReady
For me this is fine, I don't know of any other way of my website being multi-page.
But everytime that I want to go to a page it loads that page to the 'content-panel', even if it already been loaded before. I want a way to only add the page to 'content-panel' if it is not inside 'content-panel' items.
UPDATE:
Here is the loadPage
function swap(parent, replacement, url) {
var alpha = document.querySelector(parent);
var target = alpha.childNodes[0];
var omega = document.createElement(replacement);
omega.src = url;
omega.type = 'text/javascript';
alpha.replaceChild(omega, target);
}
function loadPage(panel, toPanel) {
toPanel.setLoading(true);
swap('head', 'script', panel);
}
it is used like this: loadPage('Ctl_base/view_admin/mainPage', Ext.getCmp('panel'));
I'm using CodeIgniter with ExtJS.
What I have already tried:
I want to do panel.add(loginPanel) only if the loginPanel doesn't exist.
I have tried:
if(panel.getComponent(loginScreen) == undefined) { panel.add(loginPanel); }
and it adds the component even when panel already has that component.
I have also tried:
function hasComponent(parent, child) {
parent.items.items.forEach(function(item) {
if(item == child){
return true;
}
});
return false;
}
if(!hasComponent(panel, loginPanel)) { panel.add(loginPanel); }
and it also doesn't work.
I have manage to tackle this question by putting and itemId on the panel that I want to load, and on panel.layout.setActiveItem(loginPanel); I have put panel.layout.setActiveItem('itemIdOfPanel');
Is there any direct way to get dialog object of all components which are dragged on page.
For ex: when we load page and if there is any component like text, image are on page, I can get dialog. Please suggest?
Yes, it is possible. Attach a listener which listens to the editablesready event fired by WCM. Get all the editables on the page using the #getEditables() method of CQ.WCM and then get the dialog of each editable if it is present.
Sample code below.
CQ.WCM.on('editablesready', function() {
var editables = CQ.WCM.getEditables();
for(var path in editables) {
var editable = editables[path];
try {
console.log(editable.getEditDialog());
//Do stuff
} catch(e) { }
}
});
I'm working with an EXTJS 4 dataview and having inconsistent results when adding listeners to html elements (links) in each data node. I have placed the code in the load listener on the store that is tied to the dataview. It appears to work on the first load but subsequent loads get worse as it begins missing some elements. Each time a call store.reload() it gets worse.
I have verified in firebug that the html element ID's are rendering properly but for some reason when I reload the store it begins to miss some elements at first, then all elements. Code for the load listener below:
listeners: {
load: function(store, records, successful, options){
var nodes = records;
for (i=0, len = nodes.length; i < len;i++){
var id = nodes[i].data.id;
var addtocartel = Ext.get('img-cart-'+id);
var viewel = Ext.get('img-view-'+id);
//Setting hidden class for nonimage items
switch (nodes[i].data.type) {
case 'image' :
viewel.addCls('imgprf');
addtocartel.addCls('cartprf');
break;
default :
viewel.addCls('sc_hidden');
addtocartel.addCls('sc_hidden');
viewel.hide();
addtocartel.hide();
break;
}
if(addtocartel !== null){
addtocartel.itemid = id;
addtocartel.on('click', function(e,t){
var el = Ext.get(t);
var imgrec = imagestore.getById(el.itemid);
e.stopEvent();
prfproductwindow.show();
});
}
if(viewel !== null){
viewel.itemid = id;
viewel.on('click', function(e,t){
var el = Ext.get(t);
var imgrec = imagestore.getById(el.itemid);
});
}
}
}
}
Refreshes to the grid view can happen without any sort of load occurring. When the grid view refreshes it wipes out the existing html elements and creates new ones, so any listeners you had attached to those elements will be useless.
You should look into adding a click listener to your entire grid and using a delegate to listen for clicks on specific html elements within the view. This will allow you to add a single listener once that will always work no matter how many times the elements within the view are rerendered.
grid.getView().getEl().on('click', function(evt, target) {
console.log('clicked on ' + target);
}, {delegate: '.my-css-selector-for-some-element'});
The click handler will only be fired for clicks on elements that match the delegate selector.
Also, the logic where you are adding css classes based on the record's type should be done in the renderer (if you have a grid) or handled by the data view's template.
My app has a main region and some times there will be sub regions in the main region that should be accessible by an URL. The main region content is changed by a function the app router cause he knows the main region. But whats about the temporary regions in sub views?
So for example the url /docs will show a list of links to documents and /doc/:id should show the content of the doc beside the list. So how can /doc/:id could render the content when some one click on the list and render both list and content when some opens the url in a new tab for example.
As far as I can see there are two options having a router for every region, or the region manager fires events with route and region that should change. Any hints for the best way to solve this problem.
Ok I came up with a one router for every region solution. The router is easily configurable by a map of routes and views. When ever a route match the initially passed region will be shown a new instance of the view.
Here is an advanced version of the router where the route parameter will passed into the view.
Update
The solution above only works as long every route is registered only once. If you register the same route for the second time the callback for the first one will be overridden. So I came up with a solution where the region controller register a route not directly on the router but listen to an route:change event on a global eventbus (Marionette.Application.vent), and the router triggers an route:change event on this event bus.
RouterController:
// The problem with backbone router is that it can only register one function per route
// to overcome this problem every module can register routes on the RouterController
// the router will just trigger an event on the `app.vent` event bus when ever a registered routes match
define(function() {
function RouterController(vent) {
this.vent = vent;
this.router = new Backbone.Router();
}
RouterController.prototype = _.extend({
//just pass the route that change you wanna listen to
addRoutes: function(routes) {
_.each(routes, function(route) {
this.router.route(
route,
_.uniqueId('e'),
//create a closure of vent.trigger, so when ever the route match it simply trigger an event passing the route
// _.partial(_.bind(this.vent.trigger, this.vent), 'route:change', route)
_.bind(function() {
this.vent.trigger.apply(this.vent, ['route:change', route].concat(_.toArray(arguments)));
}, this)
);
}, this);
}
},
Backbone.Events);
return RouterController;
});
RegionRouter:
define(['common/App'], function(app) {
function RegionRouter(region, routerSettings) {
app.router.addRoutes(_.keys(routerSettings));
this.listenTo(app.vent, 'route:change', function() {
var route = arguments[0];
var View = routerSettings[route];
if (!View) {
return;
}
var params;
if (arguments.length > 1) {
params = computeParams(arguments, route);
}
region.show(new View(params));
});
}
RegionRouter.prototype = _.extend(
{
onClose: function() {
this.stopListening(app.vent);
}
}, Backbone.Events
);
function computeParams(args, route) {
args = Array.prototype.slice.call(args, 1);
//map the route params to the name in route so /someroute/:somevalue will become {somevalue: passedArgs}
//this object will be passed under the parameter key of the options
var params = {};
var regEx = /(?::)(\w+)/g;
var match = regEx.exec(route);
var count = 0;
while (match) {
params[match[1]] = args[count++];
match = regEx.exec(route);
}
return {params: params};
}
return RegionRouter;
}
);