0

In Appcelerator Titanium I'm creating a label which initially is set to some text. I then add a button which when clicked calls the scanController module, and that module needs to change that text. So within scanController I'm calling the setResultTxt() method in the scanView module you see below. But when do that it says that myResultTxt is null! Why is that?

I'm still using Titanium SDK 1.7.5 because I have trouble upgrading to a newer version.

This is a complete working example of the problem:

app.js

var win = Titanium.UI.createWindow({  
    backgroundColor:'#fff',
    layout:"vertical"
});
win.open();

var module = require('scanView');

module.createScanPage(win);

scanView.js

var myResultTxt, theButton;

exports.createScanPage = function(theWindow) {
    myResultTxt = Ti.UI.createLabel({
        text: 'Some initial text',
        top:40,
    });
    theWindow.add(myResultTxt);

    theButton = Ti.UI.createButton({
        title: 'Do something',
        top:20
    });
    theButton.addEventListener('click', function() {
        alert('clicked');
        var b = require('scanController');
        b.startScanning();
    });
    theWindow.add(theButton);
};

exports.setResultText = function(str) {
    myResultTxt.text = str;
};

scanController.js

exports.startScanning = function() {
    var a = require('scanView');
    a.setResultText('My new text');
};
TheStoryCoder
  • 3,403
  • 6
  • 34
  • 64
  • I run your code using Titanium SDK 3.1.4 and it worked properly. Either the problem is in different part of code or it's issue with old SDK and it would be better to figure out how to update to latest version. – daniula Nov 13 '13 at 06:42

1 Answers1

0

Although circular references should work with CommonJS (This thread suggests it) I personally avoid them as you might get unexpected results, most of all with Titanium and different platforms.

You could work with callbacks or eventListeners, either would do in your case.

Here is an example for the callback solution:

scanView.js

theButton.addEventListener('click', function() {
     var b = require('scanController');
     // You could pass an existing function as well 
     b.startScanning(function(response) {
         if(response && response.text) {
             myResultTxt.text = response.text;
         }
     });
});

scanController.js

exports.startScanning = function(callback) {
    callback({ text:'My new text'});
};


Edit:
To make setText available from any module, you could set a global eventListener. (I know some consider this bad practice, mainly because of possible memory leaks, but if you clean up behind you it is a valuable feature).

app.js

Ti.App.addEventListener('app:setScanText', module.setResultText);


scanController.js

exports.startScanning = function() {
    Ti.App.fireEvent('app:setScanText', { text: 'My new text' });
};


scanView.js

exports.setResultText = function(response) {
    if(response && response.text) {
        myResultTxt.text = response.text;
    }
};

This is untested.

Community
  • 1
  • 1
mwfire
  • 1,657
  • 13
  • 21
  • That's a good suggestion but it can't be used in my project because `startScanning()` is also called from other modules... it's not only called from within the `scanView` module that also created the label. So I need to find a solution on how to reach `myResultTxt` from anywhere in my project... – TheStoryCoder Nov 13 '13 at 11:58
  • Ah I see, I have updated the above code with a eventListener example. – mwfire Nov 13 '13 at 13:14
  • I tried that as well but `myResultTxt` is still undefined when accessed with `setResultText()`. I think I have to give up using CommonJS and go back to attaching all properties and methods to a single global object... – TheStoryCoder Nov 16 '13 at 18:00
  • Hmmm, is the setResultTxt function called when the event is fired? Have you tried putting an alert/debug in the function to check what the response is? – mwfire Nov 16 '13 at 18:14
  • Yes, setResultText is called and the argument correctly holds what was passed to it. But for some reason myResultTxt isn't referring to the original myResultTxt and it is just undefined. I'm pretty sure now it's a bug in that old SDK... – TheStoryCoder Nov 16 '13 at 19:43