Qooxdoo Access Dynamic Properties from another class? - qooxdoo

I'm trying to access the selectedObs property of this class:
qx.Class.define("edd.view.ObsToggleContainer", {
extend : qx.ui.container.Composite,
type: "singleton",
properties : {
selectedObs : { check: "Array"}
},
construct : function() {...
from another class like this:
var ObsToggle = edd.view.ObsToggleContainer.getInstance();
console.log(ObsToggle.getSelectedObs());
But it seems to not know about what the values are presently set to. Am I doing something wrong or is there some logic that I'm not aware of?
Thanks for any help you can give!

I ended up just making a separate class as just a qx.core.Object and used that instead of a singleton Composite class and it seemed to do what I wanted to accomplish.
qx.Class.define("edd.data.DataStore", {
properties : {
checkedObs: {
init: [false, true, true, false, false, false, false, false, true, false, false, false],
check: "Array"
}
},
extend : qx.core.Object,
type: "singleton",
construct : function() {
var thisClass = this;
},
members :{
}
});
So now, this code properly works:
var dataStore = edd.data.DataStore.getInstance();
var init_checked = dataStore.getCheckedObs();

Uhm. There's something else here. Your initial class definition and the one from your own answer are not far apart, as far as the property is concerned. Maybe in the rest of your initial class, or in the code using it, was something awry?!
Have a look at this Playground sample, which uses your initial class definition. You have to open the "Log" pane, in order to see the output. Works like a charm.
It would be very interesting if you could change this sample, and tweak it until it reproduces your problem?!

Related

Using the MediaPicker property editor in custom property (Umbraco)

I want to create a custom property editor, that makes use of the media picker. Right now my controller looks like this:
angular.module("umbraco").controller("My.MediaCropperController",
function($scope, dialogService) {
$scope.mediaPicker = {
view: 'mediapicker',
value: null, // or your value
config: { disableFolderSelect: true, onlyImages: true }
};
});
And my view looks like this:
<umb-editor ng-controller="My.MediaCropperController" model="mediaPicker" ng-if="mediaPicker">
</umb-editor>
As I understand it, I need to create config object for built-in editors, then use in the template to show the editor. However when i bring my property editor into my backoffice, nothing is being shown. What am I doing wrong here?
This is my package manifest file:
{
//you can define multiple editors
propertyEditors: [
{
/*this must be a unique alias*/
alias: "My.MediaCropper",
/*the name*/
name: "My Media Cropper",
/*the html file we will load for the editor*/
editor: {
view: "~/App_Plugins/MediaCropper/mediacropper.html"
}
}
]
,
//array of files we want to inject into the application on app_start
javascript: [
'~/App_Plugins/MediaCropper/mediacropper.controller.js'
]
}
dialogService.mediaPicker rather than $scope.mediapicker ?
May be what is causing your error, just from comparing my script to yours.

Backbone fetching a model: Parsing format in array of objects

My model in the server-side has an attribute which is an array of objects. In the client-side I'm trying to fetch that model in a backbone's model.
After fetching the model from my server I get this object:
{
round: 17,
username: bob,
football_bets: [
0: { one: true, x: false, two: false },
1: { one: false, x: false, two: true },
2: { one: true, x: true, two: false },
]
}
However, I was expecting something like this:
{
round: 17,
username: bob,
football_bets: [
{ one: true, x: false, two: false },
{ one: false, x: false, two: true },
{ one: true, x: true, two: false },
]
}
I understand that this is something related with how backbone parses the result of a fetch action, but I don't know how I should deal with.
Should I override the parse method of the model to get the result as I expect?
Should I use collections instead of trying to model everything inside of a single model?
Should I use some third-party library to deal with nested objects?
I really appreciate any kind of suggestions!
The format google-chrome console adopts for arrays is like the first array I've posted in the question. I was thinking that the numbers appears before the object itself was something that backbone it was adding when you perform a fetch action ... I was thinking this because when I debugged my code I had an error that said me it was not possible to access to an attribute.
After more debugging I realize that there was an indexation problem trying to access to an undefined element ... So the conclusion of all this mess is how the google-chrome console formats arrays! Hope this helps somebody ...

Ember.js binding on array inside a property

Hello emberjs experts :)
There is something that i don't understand.
Given the following route:
Evibe.MemberShowRoute = Ember.Route.extend({
model: function(params) {
return Ember.$.getJSON('/api/user').then(function(user) {
return Ember.Object.create(user);
});
}
});
The call to the api simply returns a user object containing properties. One of this property is an array of picture objects. Like that:
{
username: "A nice user",
pictures: [
{id: 1, is_main: true, url: 'http://www.test.com/img1.jpg'},
{id: 2, is_main: false, url: 'http://www.test.com/img2.jpg'},
{id: 3, is_main: false, url: 'http://www.test.com/img3.jpg'},
{id: 4, is_main: false, url: 'http://www.test.com/img4.jpg'},
]
}
In my controller, i have something like this:
Evibe.MemberShowController = Ember.ObjectController.extend({
nb_pictures: function() {
return this.pictures.length;
}.property('pictures'),
addPictureObject: function(picture) {
this.get('pictures').addObject(picture);
}
});
And in my template, i have something like this:
{{ nb_pictures }} pictures
I don't understand why nb_pictures is not updated, as i'm adding an object into my "pictures" property with the addPictureObject function.
Also, when i try to do something like this:
this.get('pictures').setEach('is_main', false); // Works
this.get('pictures').findBy('id', pictureId).is_main = true; // Doesn't work
this.get('pictures').findBy('id', pictureId).set('is_main', true) // Doesn't work
The first line works as expected.
But... for the second line, i get the error: "Assertion failed: You must use Ember.set() to access this property (of [object Object])"
And for the third one, i get the error: "Uncaught TypeError: Object # has no method 'set' "
Any ideas that can help clarify this would be greatly appreciated.
In your nb_pictures computed property, you have set the dependent key with property('pictures'), the correct is property('pictures.length').
This is the updated code:
Evibe.MemberShowController = Ember.ObjectController.extend({
nb_pictures: function() {
return this.get('pictures.length');
}.property('pictures.length'),
addPictureObject: function(picture) {
this.get('pictures').addObject(picture);
}
});
Using just property('pictures') will make the framework observe just the array replacement, like set('pictures', [...]), not the changes in the array structure get('pictures').pushObject(...). this the reason that your ui don't update.

Problems setting up Extensible calendar

I'm trying to set up an Extensible Calendar Pro in my ExtJs 4.1 application, but I still get a name is undefined error.
EDIT:
I solved the original problem, but directly went in another.
Updated code:
Ext.define('ZeuS.view.panels.ZeusMainPanel',{
extend: 'Ext.panel.Panel',
id : 'zeusMainPanel',
alias : 'widget.zeus',
requires : [
'Extensible.Extensible',
'Extensible.calendar.CalendarPanel',
'Extensible.calendar.data.MemoryEventStore',
'Extensible.calendar.data.EventModel',
'Extensible.calendar.view.*'
],
autoShow : true,
layout : 'border',
border : false,
initComponent : function(){
this.items = [{
/*
* Some other Ext Elements
*/
}, {
region : 'east',
xtype : 'extensible.calendarpanel',
name : 'zeus-calendar',
width : 500,
eventStore: Ext.create('Extensible.calendar.data.EventStore', {
data: Ext.create('Extensible.calendar.data.EventModel',{
StartDate: '2101-01-12 12:00:00',
EndDate: '2101-01-12 13:30:00',
Title: 'My cool event',
Notes: 'Some notes'
})
})
}
];
this.callParent(arguments);
}
});
Now it loads all classes correctly when the Extensible singleton is included, but nothing works. I just have a white screen and no functions in the controller or anywhere else are called. When I remove it from the requires list it comes up with this error: Extensible.log is not a function
Do I use the plugin at all right?
Any advice?
Extensible.log is defined on the Extensible singleton, so it should always be available if your dependencies and includes are set up correctly. You really should post in the Extensible forums with additonal details (Ext version, Extensible version, script include markup) as this is basically a product support question.
EDIT: By the way, there is no such thing as Extensible.Extensible, which might be part of your problem. Also you cannot use wildcard requires statements for non-Sencha classes. You might try getting a basic example working first before trying to create a complex layout with it.

Extended ExtJS Class can't find custom listener function - "oe is undefined"

I'm adding a custom context menu to a TreePanel.
This was all working when I had a separate function for the context menu, but I was having problems where the context menu items would end up doubled/tripling up if I clicked on one of the options and then viewed the context menu again.
I had a look around for other contextmenu examples and came up with this one by Aaron Conran I pretty much "stole" it wholesale with a few additions, tacking the function directly into the Ext.ext.treePanel config. This gave me an error about "oe is undefined" which seemed to refer to "contextmenu: this.onContextMenu" in the tree config.
I figured it was probably something to do with the way I was defining all of this, so I decided to look at extending Ext.ext.TreePanel with my function in it as a learning exercise as much as anything.
Unfortunately, having managed to sort out extending TreePanel I'm now back to getting "oe is undefined" when the page tries to build the TreePanel. I've had a look around and I'm not really sure whats causing the problem, so any help or suggestions would be greatly appreciated.
Here is the code that is used to define/build the tree panel. I hope its not too horrible.
siteTree = Ext.extend(Ext.tree.TreePanel,{
constructor : function(config){
siteTree.superclass.constructor.call(this, config);
},
onContextMenu: function(n,e){
if (!this.contextMenu){
console.log('treeContextMenu',n,e);
if (n.parentNode.id == 'treeroot'){
var menuitems = [{text:'Add Child',id:'child'}];
} else {
var menuitems =
[{text:'Add Child',id:'child'},
{text:'Add Above',id:'above'},
{text:'Add Below',id:'below'}];
}
this.contextMenu = new Ext.menu.Menu({
id:'treeContextMenu',
defaults :{
handler : treeContextClick,
fqResourceURL : n.id
},
items : menuitems
});
}
var xy = e.getXY();
this.contextMenu.showAt(xy);
}
});
var treePanel = new siteTree({
id: 'tree-panel',
title : 'Site Tree',
region : 'center',
height : 300,
minSize: 150,
autoScroll: true,
// tree-specific configs:
rootVisible: false,
lines: false,
singleExpand: true,
useArrows: true,
dataUrl:'admin.page.getSiteTreeChildren?'+queryString,
root: {
id: 'treeroot',
nodeType: 'async',
text: 'nowt here',
draggable: false
},
listeners:{
contextmenu: this.onContextMenu
}
});
As a total aside; Is there a better way to do this in my context menu function?
if (n.parentNode.id == 'treeroot') {
Basically, if the clicked node is the top level I only want to give the user an add Child option, not add above/below.
Thanks in advance for your help
In your instantiation of your siteTree class you have:
listeners: {
contextmenu: this.onContextMenu
}
However, at the time of the instantiation this.onContextMenu is not pointing to the onContextMenu method you defined in siteTree.
One way of fixing it is to call the method from within a wrapper function:
listeners: {
contextmenu: function() {
this.onContextMenu();
}
}
Assuming you don't override the scope in the listeners config 'this' will be pointing to the siteTree instance at the time the listener is executed.
However, since you are already defining the context menu in the siteTree class, you may as well define the listener there:
constructor: function( config ) {
siteTree.superclass.constructor.call(this, config);
this.on('contextmenu', this.onContextMenu);
}
Ensuring the context menu is removed with the tree is also a good idea. This makes your siteTree definition:
var siteTree = Ext.extend(Ext.tree.TreePanel, {
constructor: function( config ) {
siteTree.superclass.constructor.call(this, config);
this.on('contextmenu', this.onContextMenu);
this.on('beforedestroy', this.onBeforeDestroy);
},
onContextMenu: function( node, event ) {
/* create and show this.contextMenu as needed */
},
onBeforeDestroy: function() {
if ( this.contextMenu ) {
this.contextMenu.destroy();
delete this.contextMenu;
}
}
});
I had this problem yesterday. The issue with the duplicate and triplicate items in the context menu is due to extjs adding multiple elements to the page with the same ID. Each time you call this.contextMenu.showAt(xy) you are adding a div with the ID 'treeContextMenu' to the page. Most browsers, IE especially, deal with this poorly. The solution is to remove the old context menu before adding the new one.
Here is an abridged version of my code:
var old = Ext.get("nodeContextMenu");
if(!Ext.isEmpty(old)) {
old.remove();
}
var menu = new Ext.menu.Menu({
id:'nodeContextMenu',
shadow:'drop',
items: [ ... ]
});
menu.showAt(e.xy);
I suggest never using hardcoded IDs. #aplumb suggests cleaning the DOM to reuse an existing ID. OK, but I suggest you cleanup the DOM when you no longer need the widgets/elements in the DOM and you should never reuse an ID.
var someId = Ext.id( null, 'myWidgetId' );
var someElement = new SuperWidget({
id: someId,
...
});
Just to add to owlness's answer
This bit here:
listeners: {
contextmenu: this.onContextMenu
}
Gets executed when the javascript file is loaded. this at that stage is most likely pointing to the window object.
A simple way to fix it is adding the listener on hide event of context menu, so you destroy him.
new Ext.menu.Menu(
{
items:[...],
listeners: { hide: function(mn){ mn.destroy(); } }
}
).show(node.ui.getAnchor());
;)

Resources