2

I'm wrapping chessboardjs and chessjs, two well known chess javascript libraries, into an Angular project. Everything is doing well except a method in my component .ts... this method is called by the external js library when a piece is dragged (as defined in config) and the call works. My problem is that inside this method 'onDragStart()' I can't use the class variables board and game because they seem to be undefined, even if I initialize and use them in ngOnInit(). Even a call to updateStatus() is refused as if this method couldn't see a single bit of the class. Here's the code of my component:

declare var ChessBoard: any;
declare var Chess: any;

@Component( {
    selector: 'app-chessboard',
    templateUrl: './chessboard.component.html',
    styleUrls: ['./chessboard.component.css']
} )
export class ChessboardComponent implements OnInit {

    board: any;
    game: any;

    constructor() { }


    ngOnInit() {
        var config = {
            orientation: 'white',
            draggable: true,
            position: 'start',
            moveSpeed: 'fast',
            snapbackSpeed: 100,
            snapSpeed: 100,
            pieceTheme: 'img/chesspieces/wikipedia/{piece}.png',
            showNotation: false,
            onDragStart: this.onDragStart,
        }

        this.board = new ChessBoard( 'board', config )

        this.game = new Chess();

        console.log('color of g5: ' + this.game.square_color('g5'));

        this.board.move('e2-e4');

        this.updateStatus();

    }


    onDragStart (source, piece, position, orientation) {
        // do not pick up pieces if the game is over
        if (this.game.game_over()) {return false};

        // only pick up pieces for the side to move
        if ((this.game.turn() === 'w' && piece.search(/^b/) !== -1) ||
            (this.game.turn() === 'b' && piece.search(/^w/) !== -1)) {
          return false
        };
        return true;
      }


    updateStatus () {
        var status = ''

        var moveColor = 'White'
        if (this.game.turn() === 'b') {
          moveColor = 'Black'
        }

        // checkmate?
        if (this.game.in_checkmate()) {
          status = 'Game over, ' + moveColor + ' is in checkmate.'
        }

        // draw?
        else if (this.game.in_draw()) {
          status = 'Game over, drawn position'
        }

        // game still on
        else {
          status = moveColor + ' to move'

          // check?
          if (this.game.in_check()) {
            status += ', ' + moveColor + ' is in check'
          }
        }

        console.log(status);
      }

}
```

and the error message I get when I try to drag a piece:

core.js:6014 ERROR TypeError: Cannot read property 'game_over' of undefined
    at Object.onDragStart (chessboard.component.ts:46)
    at I (chessboard-1.0.0.min.js:2)
    at HTMLDivElement.D (chessboard-1.0.0.min.js:2)
    at HTMLDivElement.dispatch (jquery.min.js:2)
    at HTMLDivElement.v.handle (jquery.min.js:2)
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:39679)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:465)

In this case is 'game' being undefined but I get the same result if I try to use 'board'.
The call to the method is correct: source, piece, position, orientation are filled with good values.
Any Idea? I just don't understand it...

Thanks a lot!

Paolo
7
  • 1
    Can you create small demo on stackblitz.com So I can take a detailed look. My guess is ngOnInit is called before the external dependencies are are loaded. Commented Aug 20, 2019 at 9:03
  • 1
    Can you show the result of this log - console.log('color of g5: ' + this.game.square_color('g5')); Commented Aug 20, 2019 at 9:07
  • 1
    @alt255: I'm gonna look stackblitz and create a demo but the code is also available at github.com/pbaioni/ChessboardNg, branch Develop, commit "stackoverflow post" Commented Aug 20, 2019 at 9:19
  • 1
    @Todarmal here's the result of the log : 'color of g5: dark' Commented Aug 20, 2019 at 10:01
  • Can you try initializing the game and board in the constructor. Please let me know if the error comes. Commented Aug 20, 2019 at 10:08

1 Answer 1

2

I finally managed to find a solution, it was a contexte problem.

The JS library was linked to a callback function by the line

onDragStart: this.onDragStart

but this leaded to a new instance of the component to be used, so everithing was undefined there.

The correct way to implement the callback was this:

onDragStart: this.onDragStart.bind( this ),

and everything is fine :)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.