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 的视图,如果是这样,我该怎么做?

第三 - 如果我还想根据客户端 javascript 上的操作触发对数据库的更新,我会将这段代码放在哪里,例如在我的代码的非 atk4 版本中,我有一个名为 using $.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 调用,并做一些 jiggery pokery 从 id 字段获取任务和状态(不确定使用 HTML5 only stufff using data- 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 更新任务。

如果我现在移动其中一个可拖动对象,它可以工作,但会打开一个新窗口,再次显示整个页面并报告

AJAXec 响应中的错误:SyntaxError:语法错误

我认为打开额外的窗口是因为错误,但错误与具有整个页面的所有 html 的响应有关。除非状态是特定的,否则我实际上不希望从 ajax 调用中重新加载。

此外,我需要做的最后一件事是仅在页面上为已更新的特定故事重新加载一个视图。

我尝试过在第一次加载页面时创建一个数组并向其中添加短变量

 $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 ; before 语句致命错误:在第 247 行的 C:\wamp\www\paperless\page\scrumwall.php 中的非对象上调用成员函数 js()


最终更新

最后一个错误是因为我没有使用我想要更新的整个视图的外部 div 中的 id。一旦我改变了它,它就不再为空了。

所以第一次加载页面时,我将所有视图名称存储在一个循环中的关联数组中,因为我将它们放在页面上

    $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();
   }

请注意,如果我只想更新页面上的一个视图,我可以通过重新加载调用该对象并执行例如

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

但是如果我想更新页面上的几个视图,我需要将它们放在一个数组中(这里称为 js[]),然后像这样调用执行 - 你也可以在 Roman 的 codepad 示例中看到一个示例。

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

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

使用 ATK4 解决了问题 :)

4

2 回答 2

1

你的结构似乎没问题。如果您在其上使用 setModel() 将具有“pointsleft”和“backlog”字段,这些字段将被自动填写。

虽然我看不到 setID 是如何定义的,但你可以扩展 setModel,调用 parent,然后也执行它。

我注意到的另一件事是,在您的模板中,最顶级的 div 应该具有 id=''。这为您的视图提供了 js() 默认使用的唯一选择器。

您正在寻找的 .post 函数是 univ()->ajaxec()。它将数据发送到服务器,接收 javascript 并执行它,因此得名。它的行为类似于表单。

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

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

通常为了使您的代码通用,您可以将上面的代码放在视图中,但最好不要使用“a”,而是使用对象的名称,就像这样。这消除了对单独的页面处理更新的需要:

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

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

更新

为了阐明它的执行顺序:

  1. 该页面被呈现为发送到您的浏览器的 HTML。
  2. 连同页面一起发送 Javascript 链。所有这些都定义了 js 的第一个参数,例如 js(true)、js('click')。在我的代码中我有 js('click') 所以它被发送到浏览器。
  3. 用户执行操作,例如单击按钮。这会触发 ajaxec() 函数
  4. ajaxec 函数使用您在此处指定的参数对页面执行 AJAX 请求。
  5. PHP 再次执行,但这次它进入 if() 分支。创建一个不带参数的 js() 并将 ->execute() 发送到浏览器。
  6. 浏览器接收 js()...->execute() 的输出并对其进行评估。在我们的例子中,它包含其他元素的 reload()。
  7. atk4_loader 小部件用于重新加载向服务器发送 AJAX 请求的页面的其他部分
  8. PHP 使用 cut_object 参数执行。它重新初始化原始页面,但仅选择性地呈现一个对象。该对象的输出被发送回前端。
  9. PHP 也像 #2 一样重新生成 JS 链,但只与该对象相关
  10. 前端的 atk4_loader 接收代码,替换元素的 HTML 并重新评估 javascript。
  11. 回到#3

这听起来像是很多动作。实际上,每次点击有 2 个请求,如果您立即重新加载,您可以消除一个。请注意,您还可以将参数传递给 reload(),然后您可以从“get”中获取这些参数。我不完全理解是什么触发了您原始脚本中的操作,也许我们可以在https://chat.stackoverflow.com/rooms/2966/agile-toolkit-atk4中找到它?

于 2011-09-30T11:22:13.140 回答
1

好的,为了获得更清晰的答案,我整理了一个示例:

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

可能这里的例子更好地回答了这个问题。

在您的情况下,由于您正在使用模型,因此设置它应该更容易。对于性能,我决定使用 2 个 Listers,但理论上您也可以将每个人和任务作为视图。

在您的情况下,我将关联存储在会话中(通过记忆),您将它们存储在数据库中。

于 2011-09-30T14:47:28.213 回答