1

現在、いくつかのデータを行に表示するページを定義しています。各行の最後に、mysql から抽出された合計を示すビューがあります。

$r->add('View_PointsLeft', 'pleft', 'pointsleft')
           ->setPoints($row['points_left'])
           ->setBacklog($row['backlog_ref'])
           ->setID($row['id'].'-points-left');

ビューは、このようなテンプレートで定義されています

<!-- points left -->
<div  class='target points_left'>
  <div class='sticky green'>
    <div class='story'><?$backlog?></div>
    <div id='<?$name?>' class='big_points big_point_margin'><?$pointsleft?></div>
  </div>
</div>
<!-- end 0000-points-left -->

ビューに入力するデータは、ループされるページ内の sql を使用して選択されます。/lib/view/pointsleft.php コードは、ページからパラメータを渡され、テンプレート内のフィールドを更新するメソッドを設定しています。

class View_PointsLeft extends View_Sticky {
  function init(){
    parent::init();
  }

  function setPoints($points){
    $this->template->set('pointsleft',$points);
    return $this;
  }

  function setBacklog($backlog){
    $this->template->set('backlog',$backlog);
    return $this;
  }

  function defaultTemplate(){
    return array('view/scrumwall/pointsleft');
  }
}

ページで何かが変更されたときにデータベースを更新し、合計ビューも更新したい (カウンターを減らすため)。

まず、これに間違った方法でアプローチしたかどうか疑問に思っています(各ビューは自己完結型である必要があります)-idフィールドをビューに渡すだけで、関連するモデルをlib/view/pointsleft.php内のビューに添付する必要がありますモデル値を使用して設定フィールドを呼び出しますか?

第二に、そのように変更すると、ajaxを使用してデータベースの値が変更されたときに、特定のIDでビューを更新しやすくなりますか?そうであれば、どうすればよいですか?

第 3 に、クライアント側の JavaScript のアクションに基づいてデータベースへの更新もトリガーしたい場合、このコードをどこに配置しますか。たとえば、私のコードの非 atk4 バージョンでは、$.post(" update.php") を使用すると、mysql が更新されます。そのようなスクリプトを ATK4 のどこに配置しますか?

前もって感謝します。


ローマ人からの回答後に更新

男、ATK4ロック!- 期待以上の機能があり、ビュー内に各フィールド名を入力する関数を作成するのに忙しかったので、addModel を使用してやり直しました。

ページからの呼び出しは次のようになります

 $r->add('View_PointsLeft', 'pleft', 'pointsleft')
               ->loadData($row['id']);

テンプレート/ビューは次のようになります

<div id='<?$name?>' class='target points_left'>
  <div class='sticky green'>
    <div class='story'><?$backlog_ref?></div>
    <div class='big_points big_point_margin'><?$points_left?></div>
  </div>
</div>

lib/view コードは次のようになります

<?php
class View_PointsLeft extends View_Sticky {

   function loadData($id){
  $this->setModel('Story')->loadData($id);
   }

   function init(){
      parent::init();
   }

   function defaultTemplate(){
      return array('view/scrumwall/pointsleft');
   }
}

ローマ人からのコード例の後に更新

Romans が提供したコード例に従った後、ページ コードの下部に jquery セレクターを使用して URL 呼び出しを追加し、id フィールドからタスクとステータスを取得するためにジグリー ポーキーを実行します (データを使用する HTML5 のみを使用するかどうかはわかりません- id なので、通常の id を設定してそこから抽出するだけです)。以前は、ドロップ コードは自分の univ.js スクリプトにありましたが、そこから php 変数にアクセスできないため、ページに移動しました。

 $p->js(true)->_selector('.movable')->draggable();
 $p->js(true)->_selector('.target')->droppable(array(
                   'drop'=>$this->js(null,'function(event,ui){'.
                           ' target=$(this).attr("id").split("-");'.
                   ' zone=target[2];'.
                               ' sticky=$(ui.draggable).attr("id").split("-");'.
                               ' task=sticky[1];'.
                               ' switch (zone) {'.
                   ' case "verify": newStatus="V";'.
                   '                break;'.
                   ' case "in":     newStatus="P";'.
                   '                break;'.
                   ' case "to":     newStatus="I";'.
                   '                break;'.
                   ' case "done":   newStatus="D";'.
                               '                break;'.
                               '}
                              $.univ().ajaxec({ 0:"'.$this->api->getDestinationURL().'",'. 
                                  'task: task, status: newStatus }); } ')
    ));

そして、ページに次のようなifブロックがあります。Model_Task を追加し、GET パラメーターに基づいて値をロードします。これにより、関連するストーリーを含む詳細情報も得られるので、ステータスが完了した場合にポイントを更新することもできます。

   if($_GET['task'] && $_GET['status'])
   {
        $new_status=$_GET['status'];
        $task_id=$_GET['task'];
        $t=$p->add('Model_Task')->loadData($task_id);
        $old_status=$t->get('status');
        $task_points=$t->get('points');

        if ($new_status<>$old_status & ($new_status=='D' | $old_status=='D'))
        {
           $s=$p->add('Model_Story')->loadData($t->get('story_id'));
           if ($old_status='D')
           {
             $s->set('points_left',$s->get('points_left')+$task_points);
           } else {
             $s->set('points_left',$s->get('points_left')-$task_points);
           }
           $s->update();

           $story=$t->get('story_id');
        }
    $t->set('status',$new_status);
    $t->update();
   }

次に、新しいポイント数を計算し、残りのポイントでストーリーを更新し、モデル値を設定して update() を使用して new_status でタスクを更新できます。

ドラッグ可能なものの 1 つを移動すると動作しますが、ページ全体とレポートを再度表示する新しいウィンドウが開きます

AJAXec 応答のエラー: SyntaxError: 構文エラー

余分なウィンドウを開くのはエラーが原因だと思いますが、エラーは、ページ全体のすべての html を持つ応答に関係しています。ステータスが特定のものでない限り、実際には ajax 呼び出しからのリロードは必要ありません。

また、最後に行う必要があるのは、更新された特定のストーリーのページのビューを 1 つだけリロードすることです。

ページが最初にロードされたときに、配列を作成し、このように短い変数を追加してみました

 $this->pl_arr[$row['id']]=$r->add('View_PointsLeft', 'pleft', 'pointsleft')
                         ->loadData($row['id']);

次に、GET の処理中に if ブロックで、それを呼び出す

       $pleft=$this->pl_arr[$story];
       $pleft->js()->reload()->execute();

しかし、それはエラーで失敗します

AJAXec 応答のエラー: SyntaxError: missing ; ステートメントの前に致命的なエラー: 247 行目の C:\wamp\www\paperless\page\scrumwall.php の非オブジェクトに対するメンバー関数 js() の呼び出し


最終更新

更新したいビュー全体の外側の div で id を使用しなかったため、最後のエラーが発生しました。これを変更すると、null ではなくなりました。

そのため、ページが初めて読み込まれるときに、すべてのビュー名をページに配置するときにループ内の連想配列に保存します

    $st = $p->add('Model_Story');
    $result = $st->getRows();

    foreach ($result as $row) {
    if (is_array($row)) {
         $r=$p->add('View_Scrumwall_StoryRow')
               ->setWorkspace('ws-'.$row['id']);

        ... other code here ...

      $points_left[$row['id']]=$r->add('View_PointsLeft', null, 'pointsleft')
                      ->loadData($row['id']);
    }

そして、このようなif GETブロックを持っています

   if($_GET['task'] && $_GET['status'])
   {
        $new_status=$_GET['status'];
        $task_id=$_GET['task'];
        $t=$p->add('Model_Task')->loadData($task_id);
        $old_status=$t->get('status');
        $task_points=$t->get('points');

        if ($new_status<>$old_status && ($new_status=='D' || $old_status=='D'))
        {
           $s=$p->add('Model_Story')->loadData($t->get('story_id'));
           if ($new_status=='D')
           {
             $s->set('points_left',$s->get('points_left')-$task_points);
           } else {
             $s->set('points_left',$s->get('points_left')+$task_points);
           }
           $s->update();
           $story=$t->get('story_id');
           //reload the points left sticky note for the story of the task
           $js[]=$points_left[$story]->js()->reload();
        }
        $t->set('status',$new_status);
        $t->update();
        $js[]=$this->js()->reload();
        $this->js(null,$js)->execute();
   }

ページのビューを 1 つだけ更新したい場合は、そのオブジェクトを呼び出してリロードして実行するだけでよいことに注意してください。

$pl->js()->reload()->実行

しかし、ページ上のいくつかのビューを更新したい場合は、それらを配列 (ここでは js[] と呼びます) に入れてから、このように execute を呼び出す必要があります。この例は、Roman のコードパッドの例でも見ることができます。

        $js[]=$points_left[$story]->js()->reload();

        $js[]=$this->js()->reload();
        $this->js(null,$js)->execute();

問題はATK4で解決しました:)

4

2 に答える 2

1

わかりました、より明確な答えのために、サンプルをまとめました:

http://codepad.agiletoolkit.org/dragaction.html

おそらくここの例は、質問によりよく答えます。

あなたの場合、モデルを扱っているので、これを設定する方が簡単なはずです。パフォーマンスのために 2 つの Lister を使用することにしましたが、理論的には、各人物とタスクをビューとして使用することもできます。

あなたのケースでは、関連付けをデータベースに保存します。

于 2011-09-30T14:47:28.213 に答える
1

Your structure seem to be OK. If you use setModel() on it which would have "pointsleft" and "backlog" fields, those would be automatically filled in.

I don't see how setID is defined though, but you could extend setModel, call parent and then execute that too.

Another thing I noticed, is in your template the most top-level div should have id=''. This gives your view unique selector which js() uses by default.

The .post function you are looking for is univ()->ajaxec(). It sends data to the server, receives javascript and executes it, hence the name. It behaves similarly to the form.

$mybutton->js('click')->ajaxec($this->getDestinationURL(null,array('a'=>'b'));

if($_GET['a']){
    // update database
    $r->getElement('plfat')->js()->reload()->execute();
}

Usually to make your code universal, you can drop this above code inside the view, but instead of 'a' you should better use the name of the object, like this. This eliminates the need for a separate page handling update:

$this->mybutton->js('click')->ajaxec($this->getDestinationURL(null,
     array($this->name=>'reload'));

if($_GET[$this->name]){
    // update database
    $this->js()->reload()->execute();
}

Update

To clarify the sequence of how it's executed:

  1. The page is rendered into HTML sent to your browser.
  2. Along with the page Javascript chains are sent. All of them which define 1st argument to js, such as js(true), js('click'). in my code i have js('click') so it's sent to browser.
  3. User performs the action such as clicking on a button. This triggers ajaxec() function
  4. ajaxec function performs AJAX request to the page with the arguments you specify there.
  5. PHP again is executed, but this time it goes inside if() branch. A js() without argument is created and ->execute() sends javascript to the browser.
  6. browser receives output of the js()...->execute() and evaluates it. In our case it contains reload() for some other element.
  7. atk4_loader widget is used to perform reload of other part of the page it sends AJAX request to server
  8. PHP is executed with cut_object argument. It re-initializes original page, but renders only one object selectively. Output for that object is sent back to the frontend.
  9. PHP also re-generates JS chains like in #2 but only relevant to that object
  10. Frontend's atk4_loader receives the code, replaces HTML of the element and re-evaluates the javascript.
  11. back to #3

It sounds like a lot of actions. In reality that's 2 requests per click and you can eliminate one if you do reload right away. Note that you can also pass arguments to reload() which you can then fetch from "get". I don't fully understand what triggers the action in your original script, perhaps we can find this out in https://chat.stackoverflow.com/rooms/2966/agile-toolkit-atk4 ?

于 2011-09-30T11:22:13.140 に答える