show/hide panel in ExtJS - javascript

I have a panel in user-interface called Code, I dont want to display that panel to specific users when they log in based on their roles. I am new to ExtJS. I have the algorithm/condition to block user's , but I am unsure where to apply it in this code. The .js file is:
analysisCodePanel = new Ext.Panel( {
id : 'analysisCodePanel',
title : 'Code',
region : 'center',
split : true,
height : 90,
layout : 'fit',
listeners :
{
activate : function( p ) {
GLOBAL.IDs[1] = null;
GLOBAL.IDs[2] = null;
p.body.mask("Loading...", 'mask-loading');
runAll(Data, p);}
return;
},
deactivate: function(){
},
collapsible : true
});
My condition is check whether user is Admin so I can do GLOBAL.IsCodeAdmin() then show the above panel else hide it from the user logged in.

if this panel is a child of viewport then you have to use your controller to show and hide the panel.
In your controller put listener for viewport rendering like below. Make sure your read docs and getting started carefully. Then I'll understand how to control elements using different events. This link is a good start http://docs.sencha.com/extjs/4.2.1/#!/guide/getting_started
// ExtJs controller
Ext.define('app.controller.ViewPortController', {
extend: 'Ext.app.Controller',
refs: [
{
ref: 'myPanel', // this elemenet can be referred as getMyPanel()
selector: 'panel[id=analysisCodePanel]' // selector to get panel reference
}
],
init: function () {
this.control({
'viewport': {
'render': this.viewPortRender // on viewport render this function will be called
}
})
},
viewPortRender: function () {
if (GLOBAL.IsCodeAdmin()) {
this.getMyPanel().show(); // show panel
} else {
this.getMyPanel().hide(); // hide panel
}
}
}
);

I solved the problem by using an attribute for panel called disabled and setting it to true.

Related

Mithril show component on button click

I have to developp an Single Application Page, i choose Mithril.
I need to render a component on button click, this is my code :
var accountView = {
controller: function (data) {
return {
showOtherPage: function () {
??? how to render an other component ?
}
}
},
view: function (ctrl) {
return [
m("button", { onclick: ctrl.showOtherPage }, "Account")
];
}
}
Thanks in advance
If you're using Mithril's routing functionality and want to show a whole new page, then you can use a link rather than using a button. (Personally, this is how I normally anticipate handling these scenarios.) eg,
m("a[href=/otherPage]", { config: m.route }, "Account")
Fiddle: https://jsfiddle.net/11qjx341/
(Alternatively, you could also call m.route('/otherPage') within the showOtherPage function if a link is not appropriate for some reason.)
Or, if you're not using Mithril's routing (eg if you're using m.mount), but still want to render a whole new page, you might want to call m.mount with the new view to have it rendered. eg
m.mount(document.body, otherView);
Fiddle: https://jsfiddle.net/91g9db6n/
As a third option, if your new view is actually meant to coexist with the current page, you can have a component that's shown or hidden based on state. eg
return [
m("button", { onclick: ctrl.showModal.bind(ctrl, !showModal) }, showModal ? "Hide Account" : "Account")
, showModal ? m.component(OtherView) : null
];
Fiddle: https://jsfiddle.net/mk27tfq1/

Using views of different controllers

Well, i have a application with a controller, that have all the logic of a grid panel for downloads, this grid panel is a view of controller (the grid who list the archives and an icon to download). Now i have a form who is managed by another controller and i need to put this grid inside of him, and this grid needs to use the functions by the archive controller. This is possible without replication of code? I'm trying do to something like this
function init() {
this.callParent(arguments);
this.control({
'academico-etpPersonalizadaForm': {
hide: this.onAcdEtpPersonalizadaFormHide,
afterrender: this.onEtpPersonalizadaRender
},...
formWidget.add(Ext.create('CoordSa.view.arquivo.List'),{
width: 500,
heigth: 600
});
But i'm getting this error
[E] Layout run failed
The 'formWidget' is the view who i want to render the grid downloader inside.
function onEtpPersonalizadaRender(formWidget) {
// console.log(record);
var x = formWidget.add({
title: 'Teste',
name: 'downloadgrid',
xtype: 'arquivoList',
width: 800,
heigth: 1000
});
console.log(x);
x.filters.addFilters({
'pssEtapa.pssEtpCodigo' : 1619
});
}
This actually show the grid, but now i have another problem, nothing appear inside of him, look the request
filter:[{"type":"numeric","comparison":"eq","value":"1619","field":"pssEtapa.pssEtpCodigo"}]
page:1
start:0
limit:0
sort:[{"property":"arqDescricao","direction":"ASC"}]
map:arqCodigo,arqNome,arqTipo,arqDescricao,pssEtapa.pssEtpCodigo,pssInscricao.pssInsCodigo,pssEdtCodigo,
And now the response
{
"success" : true,
"totalCount" : 2,
"items" : []
}
I need the data of the attribute 'map', but for some reason nothing comes back.

Smart file component(html5smartfile) not working

I have been working on developing a custom extjs console to enable author drop an asset using html5smartfile component. But somehow, the html5smartfile component is not working the way it should. The Area where an author can drop an asset is not displaying. The same is working fine if I am creating a CQ5 dialog. But in my case where i have created a window it's not working.
I have declared my smartfile component like this:
var assetLinkDropField = {
xtype: 'html5smartfile',
fieldLabel: 'Asset Link',
ddAccept: 'video/.*',
ddGroups: 'media',
fileReferenceParameter: './linkUrl',
name: './linkUrl',
allowUpload: false,
allowFileNameEditing: false,
allowFileReference: true,
transferFileName: false
};
But this is rendering like this:
After a lot of work, I found out that the CQ5 dialog updates the view for the component but in case of my window, I have to update it myself. Thus, with a slight manipulation, i just succeeded in displaying the drag area by tweaking the declaration like this:
var assetLinkDropField = {
xtype: 'html5smartfile',
fieldLabel: 'Asset Link',
ddAccept: 'video/.*',
ddGroups: 'media',
fileReferenceParameter: './linkUrl',
name: './linkUrl',
allowUpload: false,
allowFileNameEditing: false,
allowFileReference: true,
transferFileName: false,
listeners: {
afterlayout: function () {
this.updateView();
}
}
}
So now the panel looks like:
But still the Drag and Drop is not working. My Window declaration is like this:
win = new CQ.Ext.Window({
height : 750,
width : 700,
layout : 'anchor',
// animateTarget : btn.el,
closeAction : 'close', // Prevent destruction on Close
id : 'manageLinkWindow',
title : '<b>Multi Link Widget Dialog</b>',
frame : true,
draggable : false,
modal : false, //Mask entire page
constrain : true,
buttonAlign : 'center',
items : [assetLinkDropField]
});
}
I think you should not use
ddAccept: 'video/.*',
This allows only videos from the content finder to be dragged and dropped. It should be "image/".
Verify your other extjs properties / configs for html5smartfile if the above doesn't resolves your problem.

Backbone.js router/views logic

I am writing my first Backbone.js application and I am having some trouble figuring out the best way to program it. I have 2 main views:
Shows an index of all my models.
Shows a specific model for editing.
But #2 has many different 'modules' like I can edit the 'news' section, or 'about' section etc...
All these modules are in a navigation bar.
That navigation bar is hidden when I am displaying view # 1 (index of all models). It is visible in view # 2(a specific model) in order to navigate between different modules.
I have routes setup like this:
routes: {
'', 'index',
'communities': 'index',
'communities/:id': 'main',
'communities/:id/news', 'news',
'communities/:id/about', 'about'
},
So my question is, when 'news' or 'about' action is called, do I add a navigation bar in each method? Isn't that redundant? I am going to have like 8-10 different modules, add navigation bar each time seems very repetitive. Is there a better way?
The only time I want the navigation bar to be hidden is when showing index.
I came across this same problem when I created my first somewhat complex Backbone app. Along with your concern of redundant code, I was concerned about events bound to my navbar that may not get unbound as the navigation bar changed. To solve the problem, I wound up creating a view hierarchy, with one manager view managing the navigation bar a whole, and separate views for each type of navigation menu I wanted to display, which would be passed to the manager view to render to the page.
Here's an example of my implementation.
Before we start, here is a close function I added to Backbone's View prototype which unbinds events and removes the view
Backbone.View.prototype.close = function() {
if(this.beforeClose) { this.beforeClose(); }
this.remove();
this.unbind();
}
First, here is my Manager View. Its render function closes whatever menu is currently displayed and replaces it with the one passed to it as view. While slightly redundant, I created an explicit empty function to make my router code easier to understand.
var App.Views.SubNavBar = Backbone.View.extend({
currentView: null,
el: '#subnav-wrap',
render: function(view) {
if(this.currentView) { this.currentView.close(); }
this.currentView = view;
this.$el.html(view.el);
},
empty: function() {
if(this.currentView) { this.currentView.close(); }
this.currentView = null;
}
});
Second, here is a base view that all of my specific navigation menu views extend. Since they will all have the same tagName, className, id, and initialize and render functions, this keeps repetition to a minimum
var App.Views.SubNavBase = Backbone.View.extend({
tagName: 'ul',
className: 'nav nav-pills',
id: 'subnav',
template: _.template($('#tmpl-subnav').html(),
initialize: function() {
if(this.setLinks) { this.setLinks(); }
this.render();
},
render: function() {
this.$el.html(this.template({links:this.links}));
return this;
}
});
Here is an example of a view for a specific navigation menu. You can see that all I need to do is define the links I want to appear in the menu. When I instantiate this view, the functions of SubNavBase will handle populating the view with the required HTML. Note that I also have some events attached to this view.
var App.Views.Projects.DisplayNav = App.Views.SubNavBase.extend({
setLinks: function() {
this.links = {
'Edit Project': {
icon: 'edit',
class: 'menu-edit',
href: '#projects/'+this.model.get('id')+'/edit'
},
'Add Group': {
icon: 'plus',
class: 'menu-add-group',
href: '#projects/'+this.model.get('id')+'/groups/new'
},
'Delete Project': {
icon: 'trash',
class: 'menu-delete',
href: '#'
}
}
},
events: {
'click a.menu-delete' : 'delete'
},
delete: function(e) {
e.preventDefault();
// here goes my code to delete a project model
}
});
Now, here is the underscore.js template I use to turn the links object above into a list of <li> elements. Note that I use <# instead of <% for my templates since this is a rails app and rails already uses <%
<script type="text/template" id="tmpl-subnav">
<# _.each(links,function(link, title) { #>
<li>
<a href="<#= link.href #>" class="<#= link.class #>">
<i class="icon-<#= link.icon #>"></i>
<#= link.title #>
</a>
</li>
<# }); #>
</script>
Finally, to put it all together, here is an example Router function that creates and renders the nav menu. The steps that occur are as follows:
App.Views.Projects.DisplayNav gets passed a model and populates its this.el with the corresponding HTML, as determined by the underscore.js template
App.SubNavBar has its render function called with the new menu view
App.SubNavBar checks to see if there is currently another menu in the navigation bar; if so, it calls its view's close() function
App.SubNavBar finally appends the passed view's HTML to itself, maintaining a reference to the view for later use
I've included only the relevant parts of the router code
var App.Routers.Projects = Backbone.Router.extend({
routes: {
'projects/:id' : 'display'
},
display: function(id) {
var p = projects.get(id);
var subnav = new App.Views.Projects.DisplayNav({model:p})
App.SubNavManager.render(subnav); // App.SubNavManager is an instance of App.Views.SubNavBar
}
});
The benefit to all of this is that I can now attach events to my menu-specific views, and the manager view will take care of unbinding them if the user navigates to different content and the menu changes.
Of course, there are many other patterns you can use to handle navigation menus, but hopefully this will help you on the path.
Try this:
routes: {
'', 'index',
'communities': 'index',
'communities/:id': 'main',
'communities/:id/:section': 'openSection'
},
openSection : function(id, section){
if( section ){
this.addNavigationBar();
}
switch( section ){
case 'news' :
this.news();
break;
case 'about' :
this.about();
break;
default:
this.main();
}
}
If your url contents a section you will add the navigation bar and then call you normal method as you have.

ExtJS AJAX TabPanel tab load event?

Is there any way to add an event listener to the load/update event of a ajax based tabpanel in ExtJS v3.3.1? I need an event that fires after the tab content is retrieved and fully rendered, not right after the tab is selected/activated and the loading spinner is displayed.
I thought I would be able to add this event on the Ext.Updater object returned by the tabpanel's getUpdater() method, i.e.:
myTabs.getUpdater().on('update', function()
{
console.log('tab loaded');
});
But that does not seem to work. Any ideas?
Edit: Here's my full implementation to make it easier to see what I'm trying to do:
var myTabs = new Ext.TabPanel(
{
id : 'rec_tabs',
activeTab : 0,
enableTabScroll : true,
padding : 5,
autoWidth : false,
autoHeight : true,
border : false,
plain : true,
defaults : { autoHeight: true },
items :
[
{ title : 'Tab #1', autoLoad : { url : 'tab1_content.php', scripts : true } },
...
]
});
myTabs.render('tab_div');
myTabs.getUpdater().on('update', function()
{
console.log('tab loaded');
});
Finally figured it out. I hadn't realized that the properties of the "autoLoad" config object for each item of the TabPanel are actually just used as parameters for the Ext.Updater.update() method. So all I had to do was is along with the "url" and "scripts" parameters, is define the "callback" property as a function to be executed when the tab content is finished loading into its body, and its good to go.
Have you tried this?
myTabs.on("afterrender", function() {
console.log('tab loaded');
});

Categories

Resources