PDA

View Full Version : Can't access variable class Textfield value



neo4200
12 Sep 2008, 6:21 AM
Hi,

I have an object extending Ext.FormPannel

I declare all fields as class variable at the beginning of my class

eg :

APP.SearchContactForm= Ext.extend(Ext.FormPanel, {
nomField:null,
......then i assign my class variables like this :


this.nomField = new Ext.form.TextField({
id:'nomField',
....
});then i apply all properties to my extended object in the initComponent function


Ext.apply(this,{ items:[
layout:'form',
items:[this.nomField],
buttons:[{
text:'submit',
handler:this.submit,
scope:this
]}
});in the submit function i'm doing a simple processing like


alert(this.nomField.getValue())and it always displays 'undefined' except if i set a initial value like this


this.nomField = new Ext.form.TextField({
id:'nomField',
value : 'init'
});but even if i change this value by typing something different in the field it still displays 'init' in the alert.

the only way to make it works is calling


Ext.get('nomField').getValue()What's wrong with my approach.

Sorry if it's a silly question, i started Ext like 2 days ago. and it's my first application.

here is the file containing the source code :

http://cm.mcarnolds.be/inc/js/application/ContactGrid.js

thx for the help

13 Sep 2008, 7:23 AM
1) It works for me:
[code]
Ext.ns('APP');
APP.AddContactForm = Ext.extend(Ext.FormPanel, {
nomField:null
,prenomField:null
,sexeField:null
,dateNaissanceField:null
,parent:null
,initComponent:function() {
this.initFields();
Ext.apply(this,
{
bodyStyle:'padding:5px'
,width: 600
,items: [{
layout:'column'
,border:false
,items:[{
columnWidth:0.5
,layout: 'form'
,border:false
,items: [this.nomField, this.prenomField, this.sexeField]
},{
columnWidth:0.5
,layout: 'form'
,border:false
,items: [this.dateNaissanceField]
}]
}],
buttons: [{
text: 'Ajouter'
,handler: this.processAddContact
,scope : this
},{
text: 'Cancel'
,handler: this.hideWindow
,scope:this
}]
}
);
this.resetAllField();
APP.AddContactForm.superclass.initComponent.apply(this, arguments);
} // eo function initComponent

,onRender:function() {
APP.AddContactForm.superclass.onRender.apply(this, arguments);

} // eo function onRender

,initFields:function(){
this.prenomField = new Ext.form.TextField({
id: 'prenomField',
fieldLabel: 'Prenom',
maxLength: 50,
allowBlank: false,
anchor : '95%',
maskRe: /([a-zA-Z0-9\s]+)$/
});
this.nomField = new Ext.form.TextField({
id: 'nomField',
fieldLabel: 'Nom',
maxLength: 50,
allowBlank: false,
anchor : '95%',
maskRe: /([a-zA-Z0-9\s]+)$/
});
this.sexeField = new Ext.form.ComboBox({
id:'sexeField',
fieldLabel: 'Sexe',
store:new Ext.data.SimpleStore({
fields: ['sexeValue', 'sexeDisplay']
,data:[['M','Masculin'],['F','F

neo4200
14 Sep 2008, 7:56 AM
1) Why can't I access my field value with this.nomField.getValue() ?

2) I know it's kinda mixed, I adopted right coma, but as I said this is my first EXt app and there is some copy/paste code and I didn't change it yet.

3) You're totally right

Animal
14 Sep 2008, 8:01 AM
1) Why can't I access my field value with this.nomField.getValue() ?

It depends what "this" refers to at the time that statement runs. Set a breakpoint on that line, and when it breaks, examine what "this" is.

neo4200
14 Sep 2008, 8:06 AM
It depends what "this" refers to at the time that statement runs. Set a breakpoint on that line, and when it breaks, examine what "this" is.

If "this" don't point to the right object at that stage, this.nomField would be undefined. Even this.nomField.id is working. It seems the the field value is set once and then no matter i change it's value I keeps the initial one. look at my initial post you'll see what I mean

Animal
14 Sep 2008, 8:29 AM
Debug it. Break at that line, step into the code, see what it's doing.

14 Sep 2008, 8:52 AM
Where is alert(this.nomField.getValue()) being called?

do a console.log(this) and see what that is.

neo4200
14 Sep 2008, 10:01 AM
ok I did a console.log(this) in the initComponent function and got that
Object initialConfig=Object xtype=SearchContactForm

then i did the same in the function supposed to read the fields value and got that

Object initialConfig=Object xtype=SearchContactForm


I clicked on both to see what's inside and it seem to be the same objects. does each object instance get unique id i could check to be sure it's the same object ?

mjlecomte
14 Sep 2008, 4:42 PM
Do not do console.log(this), firebug has problems with "this". Use console.dir(this). That will give you an accurate representation at the moment you execute that console statement. console.log(this) doesn't take an accurate snapshot.

neo4200
15 Sep 2008, 7:13 AM
Ok I turned the problem in every manner i could and can't figure out where the problem come from. it seems that the console.dir(this) shows an instance of the SearchContactForm object. So this seems to be refering to the right object. i'm going to do a better summary of my code hoping it helps to pinpoint the problem source.

I've a class named : SearchContactForm in the package APP
That class Extends Ext.FormPanel

here is my code :



APP.SearchContactForm= Ext.extend(Ext.FormPanel, {

nomFields:null

,initComponent:function() {
this.initFields();

Ext.apply(this
,{
bodyStyle:'padding:5px'
,width: 300

,items: [
this.nomFields
]

,buttons: [
{
text: 'Rechercher'
,handler: this.searchContact
,scope:this
}
,{
text: 'Annuler'
,handler: this.cancel
,scope:this
}
]
}
);

APP.SearchContactForm.superclass.initComponent.apply(this, arguments);
} // eo function initComponent

,onRender:function() {
APP.AddContactForm.superclass.onRender.apply(this, arguments);
} // eo function onRender


,initFields:function(){
this.nomFields = new Ext.form.TextField({
id: 'nomFields'
,value:'hello'
,fieldLabel: 'Nom'
,maxLength: 50
,allowBlank: true
,anchor : '95%'
//,maskRe: /([a-zA-Z0-9\s]+)$/
});
}

,searchContact:function(oevent){
// even if i change the field value it always displays "hello" in the console
console.log(this.nomFields.getValue());
// display the correct field value in the console but totaly break the OO concept :s
console.log(Ext.get('nomFields').getValue());
}

,cancel:function(){
;
}
});

Ext.reg('SearchContactForm', APP.SearchContactForm);
My object SearchContactForm is instanciated in another object with the folowing function :



,showSearchContactForm:function(){
this.searchContactWindow= new Ext.Window({
id: 'searchContactWindow'
,title: 'Rechercher un contact'
,closable:true
,modal:false
,width: 310
,height: 220
,plain:true
,layout: 'fit'
,items:{xtype:'SearchContactForm',id:'searchContactForm',caller:this}
});
this.searchContactWindow.show();
}
plz can you read it carefully and tell me what's wrong. I getting mad with that problem

Million thanks in advance

neo4200
15 Sep 2008, 7:34 AM
additional informations :

I tried to declare the field outside the class like this :


var field;

then i init the field in the initField function :


field =new Ext.form.TextField(....


and in my searchContact function i do


console.log(field.getValue());

result is exactly the same so it seems it has nothing to do with the scope or something.

neo4200
15 Sep 2008, 9:22 PM
noone ?

Animal
15 Sep 2008, 11:16 PM
DE. BUG. IT.

neo4200
16 Sep 2008, 1:50 AM
DE. BUG. IT.

is that supposed to help me ?:((

I finally found the problem myself and actually I don't really understand what was wrong
I had to extend a "Panel" instead of a FormPanel".

I call that random luck and not really debugging. I said i'm new to ext, and say "DEBUT IT" is not really helping, escpecially when there was NO BUG.



APP.SearchContactForm= Ext.extend(Ext.Panel, {
nomFields:null
,prenomField:null
,sexeField:null
,startDateNaissanceField:null
,endDateNaissanceField:null
,parent:null

,initComponent:function() {
this.initFields();
Ext.apply(this,
{
bodyStyle:'padding:5px'
,layout:'form'
,width: 300
,items: [
this.nomFields
,this.prenomField
,this.sexeField
,this.startDateNaissanceField
,this.endDateNaissanceField
]

,buttons: [
{
text: 'Rechercher'
,handler: this.searchContact
,scope:this
}
,{
text: 'Annuler'
,handler: this.cancel
,scope:this
}
]
}
);
APP.SearchContactForm.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
Can any1 give me an explanation of what was wrong ?

Animal
16 Sep 2008, 2:08 AM
It would have helped if you'd done it. It's easy, and saves time. Set a breakpoint, step into the code, and see what it does.

As for why it didn't work, nobody will ever know.

neo4200
16 Sep 2008, 3:37 AM
Ok my bad, I was not unterstanding what you mean. I had no knowledge of "stepping into the code", you have all my apologies. So I went back to the buggy version and I did "Step into" and noticed that when it goes through the getValue funtion it enters "if(!this.redered)"

Which it does not when I extend a simple panel


function () {
if (!this.rendered) {
return this.value;
}
var v = this.el.getValue();
if (v === this.emptyText || v === undefined) {
v = "";
}
return v;
}


I hope it's what you wanted to be able to help me ?

Sorry again animal, i was mad thinking you didn't want to help

mjlecomte
16 Sep 2008, 3:50 AM
I don't understand why you would say "there was no bug". Was it working? No? Then you had a bug. Anyway, for future information scan this one over, maybe it will save you some time in the future: http://extjs.com/learn/Ext_FAQ_Debugging.

Animal
16 Sep 2008, 3:51 AM
Bingo! That's the way to do it!

neo4200
16 Sep 2008, 3:56 AM
it will save you some time in the future: http://extjs.com/learn/Ext_FAQ_Debugging.

Yup, already went there that's how I found out what does "step into" means.


Bingo! That's the way to do it!

Ok, but now why the field wasn't render that's the next question. :D

Animal
16 Sep 2008, 4:06 AM
I don't know at what point you executed the code, but a Component only gets rendered when the Container that you add it to lays itself out. So after adding a Component you cannot assume it is rendered.

neo4200
16 Sep 2008, 4:27 AM
that code is executed a very late stage, I mean after all the components have been displayed. if you reffer to my code it's in the seachContactFunction when I do the call to : console.log(this.nomFields.getValue());

I hope this was what you were asking :p

16 Sep 2008, 4:30 AM
Do not do console.log(this), firebug has problems with "this". Use console.dir(this). That will give you an accurate representation at the moment you execute that console statement. console.log(this) doesn't take an accurate snapshot.

I find this interesting considering I use console.log to figure out which scope a method is being called and have had zero issues.


I'm not too sure how you came to that conclusing being that console.dir, according to the source, calls console.log which, in turn, calls console.logFormatted.

consoleInjector.js


Line 99+

this.log = function()
{
logFormatted(arguments, "log");
};

...
Line 136+
this.dir = function(o)
{
Firebug.Console.log(o, context, "dir", Firebug.DOMPanel.DirTable);
};
...
Line 276+
function logFormatted(args, className, linkToSource, noThrottle)
{
var sourceLink = linkToSource ? getStackLink() : null;
return Firebug.Console.logFormatted(args, context, className, noThrottle, sourceLink);
}


...
The entire consoleInjector.js


/* See license.txt for terms of usage */

//
FBL.ns(function() { with (FBL) {
// ************************************************************************************************
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

top.Firebug.Console.injector = {

attachConsole: function(context, win)
{
if (!win)
{
return;
}

if (context.stopped)
Firebug.Console.injector.evaluateConsoleScript(context);
else
Firebug.Console.injector.injectConsoleScriptTag(win);

Firebug.Console.injector.addConsoleListener(context, win);
},

evaluateConsoleScript: function(context)
{
var scriptSource = getResource("chrome://firebug/content/consoleInjected.js");
Firebug.Debugger.evaluate(scriptSource, context);
},

injectConsoleScriptTag: function(win)
{
var doc = win.document;

// Don't inject the script twice to the same document.
var element = $("_firebugConsoleInjector", doc);
if (element)
{
return;
}

// Inject script into the document via SCRIPT tag.
var scriptSource = getResource("chrome://firebug/content/consoleInjected.js");
addScript(doc, "_firebugConsoleInjector", scriptSource);
},

addConsoleListener: function(context, win)
{
var doc = win.document;

var element = $("_firebugConsole", doc);
if (!element)
{
return;
}

// Initialize Firebug version.
element.setAttribute("FirebugVersion", Firebug.version);

if (!context.consoleHandler)
context.consoleHandler = [];

for (var i=0; i<context.consoleHandler.length; i++)
{
if (context.consoleHandler[i].window == win)
return;
}

var handler = new FirebugConsoleHandler(context, win);
// When raised on our injected element, callback to Firebug and append to console
element.addEventListener('firebugAppendConsole', bind(handler.handleEvent, handler) , true); // capturing
context.consoleHandler.push({window:win, handler:handler});

}
}

function FirebugConsoleHandler(context, win)
{
this.handleEvent = function(event)
{
if (!Firebug.CommandLine.CommandHandler.handle(event, this, win))
{
var methodName = event.target.getAttribute("methodName");
Firebug.Console.log($STRF("console.MethodNotSupported", [methodName]));
}
};

this.firebug = Firebug.version;

this.init = function()
{
var consoleElement = win.document.getElementById('_firebugConsole');
consoleElement.setAttribute("FirebugVersion", Firebug.version);
};

this.log = function()
{
logFormatted(arguments, "log");
};

this.debug = function()
{
logFormatted(arguments, "debug", true);
};

this.info = function()
{
logFormatted(arguments, "info", true);
};

this.warn = function()
{
logFormatted(arguments, "warn", true);
};

this.error = function()
{
Firebug.Errors.increaseCount(context);
logFormatted(arguments, "error", true);
};

this.assert = function(x)
{
if (!x)
{
var rest = [];
for (var i = 1; i < arguments.length; i++)
rest.push(arguments[i]);
logAssert(rest);
}
};

this.dir = function(o)
{
Firebug.Console.log(o, context, "dir", Firebug.DOMPanel.DirTable);
};

this.dirxml = function(o)
{
if (o instanceof Window)
o = o.document.documentElement;
else if (o instanceof Document)
o = o.documentElement;

Firebug.Console.log(o, context, "dirxml", Firebug.HTMLPanel.SoloElement);
};

this.trace = function()
{
var trace = getJSDUserStack();
Firebug.Console.log(trace, context, "stackTrace");
};

this.group = function()
{
var sourceLink = getStackLink();
Firebug.Console.openGroup(arguments, null, "group", null, false, sourceLink);
};

this.groupEnd = function()
{
Firebug.Console.closeGroup(context);
};

this.groupCollapsed = function()
{
var sourceLink = getStackLink();
// noThrottle true is probably ok, openGroups will likely be short strings.
var row = Firebug.Console.openGroup(arguments, null, "group", null, true, sourceLink);
removeClass(row, "opened");
};

this.profile = function(title)
{
Firebug.Profiler.startProfiling(context, title);
};

this.profileEnd = function()
{
Firebug.Profiler.stopProfiling(context);
};

this.count = function(key)
{
var frameId = FBL.getStackFrameId();
if (frameId)
{
if (!context.frameCounters)
context.frameCounters = {};

if (key != undefined)
frameId += key;

var frameCounter = context.frameCounters[frameId];
if (!frameCounter)
{
var logRow = logFormatted(["0"], null, true, true);

frameCounter = {logRow: logRow, count: 1};
context.frameCounters[frameId] = frameCounter;
}
else
++frameCounter.count;

var label = key == undefined
? frameCounter.count
: key + " " + frameCounter.count;

frameCounter.logRow.firstChild.firstChild.nodeValue = label;
}
};

this.time = function(name, reset)
{
if (!name)
return;

var time = new Date().getTime();

if (!this.timeCounters)
this.timeCounters = {};

if (!reset && this.timeCounters[name])
return;

this.timeCounters[name] = time;
};

this.timeEnd = function(name)
{
var time = new Date().getTime();

if (!this.timeCounters)
return;

var timeCounter = this.timeCounters[name];
if (timeCounter)
{
var diff = time - timeCounter;
var label = name + ": " + diff + "ms";

this.info(label);

delete this.timeCounters[name];
}
return diff;
};

// These functions are over-ridden by commandLine
this.evaluated = function(result, context)
{
Firebug.Console.log(result, context);
};
this.evaluateError = function(result, context)
{
Firebug.Console.error(result, context);
};

/*
this.addTab = function(url, title, parentPanel)
{
context.chrome.addTab(context, url, title, parentPanel);
};

this.removeTab = function(url)
{
context.chrome.removeTab(context, url);
};
*/

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

function logFormatted(args, className, linkToSource, noThrottle)
{
var sourceLink = linkToSource ? getStackLink() : null;
return Firebug.Console.logFormatted(args, context, className, noThrottle, sourceLink);
}

function logAssert(args)
{
Firebug.Errors.increaseCount(context);

if (!args || !args.length || args.length == 0)
var msg = [FBL.$STR("Assertion")];
else
var msg = args[0];

var sourceName = win.location;
var lineNumber = 0;
var trace = getJSDUserStack();
if (trace && trace.frames[0])
{
var frame = trace.frames[0];
sourceName = normalizeURL(frame.script.fileName);
lineNumber = frame.line;
}

var errorObject = new FBL.ErrorMessage(msg, sourceName,
lineNumber, "", "assert", context, trace);

var row = Firebug.Console.log(errorObject, context, "errorMessage", null, true); // noThrottle
row.scrollIntoView();
}

function getComponentsStackDump()
{
// Starting with our stack, walk back to the user-level code
var frame = Components.stack;
var userURL = win.location.href.toString();

// Drop frames until we get into user code.
while (frame && FBL.isSystemURL(frame.filename) )
frame = frame.caller;

// Drop two frames to get back to the point of call for eg console.log()
if (frame)
frame = frame.caller;
if (frame)
frame = frame.caller

return frame;
}

function getStackLink()
{
return FBL.getFrameSourceLink(getComponentsStackDump());
}

function getJSDUserStack()
{
var trace = FBL.getCurrentStackTrace(context);

var frames = trace ? trace.frames : null;
if (frames && (frames.length > 0) )
{
var bottom = frames.length - 1;
for (var i = 0; i < frames.length; i++)
if (frames[bottom - i].href.indexOf("chrome:") == 0) break;

trace.frames = trace.frames.slice(bottom - i + 1);
return trace;
}
else
return "Firebug failed to get stack trace with any frames";
}
}

}});

16 Sep 2008, 4:31 AM
... Could it be the bug where you click on the object and it displays the wrong object entirely?

mjlecomte
16 Sep 2008, 5:10 AM
... Could it be the bug where you click on the object and it displays the wrong object entirely?

I'm not sure. I know I used to use console.log(this), but I noticed it was wrong sometimes or all the time even. I did not for sure confirm console.log(someOtherObject), I only did it with "this". If I recall correctly, console.log(this) would be this at some later stage, for instance when execution completed. If you're interested in testing it further do both console.log and console.dir(this) early in the creation of an object and again much later and compare.

This was FF2 and I'm not sure what version of Firebug that had the problem. I also recall seeing this discussed out in neverland (the internet) somewhere when I was encountering the problem.

16 Sep 2008, 5:13 AM
I can't reproduce it :(. Sorry for the digression, just wanted to see if i could understand the problem further :)

neo4200
17 Sep 2008, 12:39 AM
I think this can explain why the getValue function was considering that the field hadn't be rendered, does it ?



Component config objects may also be specified in order to avoid the overhead of constructing a real Component object if lazy rendering might mean that the added Component will not be rendered immediately. To take advantage of this "lazy instantiation", set the Ext.Component.xtype (http://extjs.com/forum/../deploy/dev/docs/output/Ext.Component.html#xtype) config property to the registered type of the Component wanted.

mjlecomte
19 Sep 2008, 11:39 AM
I can't reproduce it :(. Sorry for the digression, just wanted to see if i could understand the problem further :)

I'm surprised, I can reproduce the problem quite easily:

Save this to an html page and run it. Click on console statements in first test, the only one that is accurate is dir.


<html>
<head>

<script type="text/javascript">

var fx = {};
console.warn('test 1');
console.log('log:',fx);
console.info('info:',fx);
console.log('dir:');
console.dir(fx);

fx.foo = 1;
console.warn('test 2');
console.log('log:',fx);
console.info('info:',fx);
console.log('');
console.dir(fx);

fx.bar = [2, 3, 4];
console.warn('test 4');
console.log('log:',fx);
console.info('info:',fx);
console.log('dir:');
console.dir(fx);


console.warn('test WTF');
console.log('log:',fx);
console.info('info:',fx);
console.log('dir:');
console.dir(fx);
fx.something = 'WTF';
</script>
</head>
</html>

FB 1.05, FF 2.0.0.16