2

私は非常に単純なアプリを作成しようとしています: 私はいくつかのゲーム (チェス、ティクタクトなどなど) を持っており、各ゲームにはいくつかのボードがあります。ゲームのリストを表示し、ゲームをクリックするとボードのリストを表示したい。

しかし、私は多くの問題に直面しています。最初にそれらについて説明し、その後にコードを貼り付けます。

  1. ゲームのリストが正しく表示されます。ここでは問題ありません。
  2. ゲームをクリックすると、次のエラーが表示されます。

    Uncaught Error: assertion failed: an Ember.CollectionView's content must implement Ember.Array. You passed <(generated game controller):ember237>

    しかし、F5 キーを押すか、手動で URL を書き込むと、すべて正常に動作します。そして、私には理由がわかりません。

    更新:gamesテンプレートを変更{{#linkTo}}し、手書きのリンクを変更すると、すべてが正常に機能することがわかりました:

    • これは機能しない linkTo:{{#linkTo 'game' game}}{{game.name}}{{/linkTo}}です。URL は正しく作成されますが、クリックすると失敗します。
    • これは手書きの<a>タグです: <a href="#/games/{{unbound game.id}}">{{game.name}}</a>. それは完全に機能します。
  3. 各ボードの URL は次の形式に従う必要があります。

    /games/1/boards/5

    しかし、私{{#linkTo 'board' board}}が得るものを書くとき:

    /games/undefined/boards/5

コードは次のとおりです (「動作中の」コピーは JBin で確認できます。ただし、ローカル REST アプリで中継するため、機能しません)。

ルーター:

MGames.Router.map(function () {
    this.resource('games', function () {
        this.resource ('game', {path: '/:game_id'}, function () {
            this.resource('board', {path: '/boards/:board_id'});
        });
    });
});

MGames.IndexRoute = Ember.Route.extend({
    redirect: function () {
        this.transitionTo('games');
    }
});

MGames.GamesRoute = Ember.Route.extend ({
    model: function() {
        return MGames.Game.findAll();
    }
});

MGames.GameRoute = Ember.Route.extend ({
    model: function(params) {
        return MGames.Board.findAllByGame(params.game_id);
    }
});

MGames.BoardsRoute = Ember.Route.extend ({
    model: function(params) {
        return this.modelFor('game').then(
            function (game) {
                return MGames.Board.find(game.get('id'), params.board_id);
            }
        );
    }
});

モデル:

MGames.Game = Ember.Object.extend({
    id: null,
    name: null,
    icon: null
});

MGames.Game.reopenClass({
    findAll: function() {
        var url = [MGames.GAMES_API_URL];
        url.push ('games');
        url = url.join('/');

        var result = Ember.ArrayProxy.create({ content: [] });

        $.getJSON(url).then (
            function (response) {
                response.forEach(function (child) {
                    result.pushObject (MGames.Game.create(child));
                });
            }
        );

        return result;
    },

    find: function (id) {
        var url = [MGames.GAMES_API_URL];
        url.push ('games');
        url.push (id);
        url = url.join('/');

        var game = MGames.Game.create({ isLoaded: false });

        $.getJSON(url).then (
            function(response) {
                game.setProperties(response);
                game.set('isLoaded', true);
            }
        );

        return game;
    }
});

MGames.Board = Ember.Object.extend({
    id: null,
    name: null,
    owner: null,
    game: null,
    is_public: null,
    created_at: null
});

MGames.Board.reopenClass({
    findAllByGame: function (game) {
        var url = [MGames.GAMES_API_URL];
        url.push ('games');
        url.push (game);
        url.push ('boards');
        url = url.join('/');

        var result = Ember.ArrayProxy.create({ content: [] });

        $.getJSON(url).then (
            function (response) {
                console.log (response);
                response.forEach(function (child) {
                    result.pushObject (MGames.Board.create(child));
                });
            }
        );

        return result;
    },

    find: function (game, board) {
        url = [MGames.GAMES_API_URL];
        url.push ('games');
        url.push (game);
        url.push ('boards');
        url.push (board);
        url = url.join('/');

        var result = MGames.Board.create();

        $.getJSON(url).then (
            function(response) {
                result.setProperties(response);
            }
        );

        return result;
    }
});

そしてテンプレート:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>MGames</title>
  <link rel="stylesheet" href="css/bootstrap.css">
  <link rel="stylesheet" href="css/main.css">
</head>
<body>

  <script type="text/x-handlebars">
    <div class="navbar navbar-fixed-top">
      <div class="navbar-inner">
        <div class="container">
          <div class="nav-collapse collapse">
            <ul class="nav">
              <li class="active">{{#linkTo 'index' class="brand"}}MGames{{/linkTo}}</li>
            </ul>
          </div>
        </div>
      </div>
    </div>

    <div class="container">
      {{outlet}}
    </div>
  </script>

  <script type="text/x-handlebars" id="games">
    <div class="row">
      <header id="header">
        <h1>Games</h1>
      </header>
      <ul>
      {{#each game in controller}}
      <li>
        {{#linkTo 'game' game}}{{game.name}}{{/linkTo}}
      </li>
      {{/each}}
      </ul>

      {{outlet}}
    </div>
  </script>

  <script type="text/x-handlebars" id="game">
    <div class="row">
      <div class="span3" id="boards">
        <header id="header">
          <h1>Boards</h1>
        </header>

        <ul id="board-list">
          {{#each board in controller}}
          <li>
            {{#linkTo 'board' board}}{{board.name}}{{/linkTo}}
          </li>
          {{/each}}
        </ul>
      </div>
      <div class="span9">
        {{outlet}}
      </div>
    </div>
  </script>

  <script type="text/x-handlebars" id="board">
    <header id="header">
      <h1>{{game.name}} - {{name}} <small>{{owner.nickname}}</small></h1>
    </header>
  </script>

  <script src="js/libs/jquery.js"></script>
  <script src="js/libs/bootstrap.js"></script>
  <script src="js/libs/handlebars.js"></script>
  <script src="js/libs/ember.js"></script>

  <script src="js/application.js"></script>
  <script src="js/router.js"></script>
  <script src="js/models/game.js"></script>
  <script src="js/models/user.js"></script>
</body>
</html>
4

2 に答える 2

4

わかりました、私はついに問題を理解しました。私のgameRoute中で私はこれを書きました:

MGames.GameRoute = Ember.Route.extend ({
    model: function(params) {
        return MGames.Board.findAllByGame(params.game_id);
    }
});

Emberがmodel関数を呼び出すため、ブラウザバーにURLを直接書き込むと機能しましたが、モデルに従う{{#linkTo}}とパラメータとして渡されたモデルであるため、model関数は呼び出されません。

したがって、作業コードは次のとおりです (少し簡略化されています)。

MGames.GameRoute = Ember.Route.extend ({
    model: function (params) {
        // This is only called when loading the URL directly,
        // not following a link. We load the game, and in the
        // setupController we'll load the boards.
        return MGames.Game.find(params.game_id);
    },
    setupController: function(controller, game) {
        // This is *always* called, so we load the boards
        model = MGames.Board.findAllByGame(game.id);
        controller.set('model', model);
    }
});
于 2013-07-04T19:55:11.110 に答える
2

リンク先のboardルートには 2 つの動的セグメントがありますが、提供しているのは 1 つだけです。に変更する必要があります。

{{#linkTo 'board' game board}}The board{{/linkTo}}

このundefinedエラーはArrayController、対応するゲーム ID が として渡されているため、ボードを取得していないことが原因である可能性がありundefinedます。上記の変更により、それも修正されるはずです。

于 2013-07-04T17:27:26.267 に答える