error when passing "this" to another class in JS

Hi,

In this sample there is a button on the main page, once clicked it creates a new object “cardList” that contains an array and a class that draws the results on the ux (using the class “card”). That tries to emulate when u fetch 100 results and u want to draw them as the user navigates. So far so good :slight_smile:

my problem comes when i want to call the cardList.print() function inside the card class. If i pass “this” as a parameter it’s fine as long as i don’t use it. If u uncomment the line: "this.parent = parent, " in the Card class then it stops working (no error raises). If i do something like: this.whatever = parent.lastLoadedIndex it works fine.

i guess that’s a bug

my code:

MainView.ux:

<App>
<Router ux:Name="router" />

<JavaScript>
    var Observable = require("FuseJS/Observable");
    var card = require("cardClass");
    var uxList = Observable();

    function loadArray(){
        console.log("click!");
        array = new Array(1, 2, 3, 4, 5, 6, 7);

        var list = new card.cardList(uxList, array);
        list.print(0,2);
    }

    module.exports = {
        loadArray: loadArray,
        uxList: uxList
    }
</JavaScript>

<DockPanel>
    <StatusBarBackground Background="#595959" Dock="Top"/>
    <iOS.StatusBarConfig Style="Light"/>
    <BottomBarBackground IncludesKeyboard="false" Dock="Bottom"/>

    <Panel Dock="Top">
        <Button Height="30" Clicked="{loadArray}" Margin="5">
            <Text Value="Load" TextAlignment="Center" Alignment="VerticalCenter" TextColor="#fff"/>
            <Rectangle Layer="Background" CornerRadius="10" Fill="#68C4FB">
                <Stroke Width="1" Brush="#68C4FB"/>
            </Rectangle>
        </Button>
    </Panel>

    <Panel Margin="0,5,0,5">
        <LinearNavigation> 
            <NavigationMotion GotoDuration="0.4" GotoEasing="CircularOut" GotoType="SmoothSnap" Overflow="Elastic"/>
        </LinearNavigation>
        
        <SwipeNavigate SwipeDirection="Left" />

        <Each Items="{uxList}">
          <Card/>
        </Each>
    </Panel>

 </DockPanel>
 </App>

Card.ux:

<Panel ux:Class="Card" Width="90%" Height="100%">

<ActivatingAnimation>
    <BringToFront />
    <Callback Handler="{onCardShow}" AtProgress="1"/>            
</ActivatingAnimation>

<EnteringAnimation Scale="0.5">
    <Move RelativeTo="Size">
        <Keyframe X="-1.0" Time="0.6"/>
    </Move>
    <Scale Factor="0.5" Duration="1" />            
</EnteringAnimation>

<ExitingAnimation Scale="0.5">
    <Move RelativeTo="Size"> 
        <Keyframe X="1.0" Time="0.6"/>
    </Move>
    <Scale Factor="0.5" Duration="1" />
</ExitingAnimation>

<Rectangle Fill="#fff" CornerRadius="15,15,15,15">
    <Stroke Color="#000"/>
    
    <StackPanel>
        <Text Value="{hitNumber}" TextAlignment="Center" Margin="0,10,0,10"/>

        <Button Height="30" Clicked="{sayHello}" Margin="5">
            <Text Value="hello" TextAlignment="Center" Alignment="VerticalCenter" TextColor="#fff"/>
            <Rectangle Layer="Background" CornerRadius="10" Fill="#68C4FB">
                <Stroke Width="1" Brush="#68C4FB"/>
            </Rectangle>
        </Button>

        <Text Value="{text}" TextAlignment="Center" Margin="0,10,0,10"/>
        
    </StackPanel>
</Rectangle>

</Panel>

cardClass.js:

 var Observable = require("FuseJS/Observable");

 function Card(json, parent){

this.hitNumber = json.hitNumber.toString(),
this.text 	   = Observable(),
//IF I UNCOMMENT THAT LINE IT STOPS WORKING
//this.parent    = parent, 

this.sayHello = function(){
	this.text.value = "hello: " + this.hitNumber;
}.bind(this),

this.onCardShow = function(){
	//I WOULD LIKE TO CALL this.parent.print(from, to);
}.bind(this)

}

function cardList(uxCardList, arrayPlaces){
this.arrayPlaces     = arrayPlaces,
this.uxCardList 	 = uxCardList
this.lastLoadedIndex = -1,

this.print = function(fromIndex, toIndex) {
	  if (fromIndex <= this.lastLoadedIndex) {
	  	fromIndex = this.lastLoadedIndex + 1;
	  }

	  if (toIndex <= this.lastLoadedIndex) {
	    return "";
	  }

	  if (toIndex >= this.arrayPlaces.length) {
	  	toIndex = this.arrayPlaces.length-1;
	  }

	  if (toIndex < fromIndex) {
	  	return "";
	  }

	  for (var iHitNumber=fromIndex; iHitNumber <= toIndex; iHitNumber++) {
	    jsonAdd = {
	    	hitNumber: this.arrayPlaces[iHitNumber]
	    }
	    console.log("add card");
	    var card = new Card(jsonAdd, this);

	    this.uxCardList.add(card);
	  }

	  this.lastLoadedIndex = toIndex;
	  	
}

}

module.exports = {
   cardList: 			cardList
};

Hey zaulin,
it seems that there is an issue with data contexts being messed up.

Here’s something that should clear it up for you:

function MyClass(id) {
    this.id = id; // we can use 'this.*' here, as that is the data context of our MyClass object
    var self = this; // create a reference to 'this' that can be used in lower data contexts
    this.printId = function() {
        console.log(this.id); // will yield 'undefined', since the scope of 'this' is the function 'printId()' we are in
        console.log(self.id); // will print '123'
    };
}
var tmp = new MyClass(123);
tmp.printId();

Hello Zaulin,

If what Uldis suggested doesn’t help, can you make a minimal reproduction of the issue? I tried your app and there does indeed seem to be something fishy going on, but it’s currently a bit hard to tell why that is.

Cheers,
Olle