в ATK4, как я могу использовать AJAX для обновления представления - PullRequest
1 голос
/ 30 сентября 2011

У меня в настоящее время определена страница, которая отображает некоторые данные в строках. В конце каждой строки есть представление, которое показывает сумму, извлеченную из 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, и если да, то как мне это сделать?

В-третьих, если я хочу также запустить обновление базы данных на основе действия на клиентском 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');
   }
}

Обновление после примера кода от римлян

После следования примеру кода, предоставленного римлянами, я теперь добавляю URL-вызов с помощью селекторов jquery в нижней части кода моей страницы и выполняю некоторые покерные игры, чтобы получить задачу и статус из полей id (не уверен насчет использования HTML5 только stufff используя 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();
   }

Затем я могу рассчитать новое количество точек и обновить историю с оставленными точками, а также обновить задачу с помощью new_status, задав значения модели и используя update ().

Если я сейчас переместлю один из перетаскиваемых объектов, он будет работать, но откроется новое окно, в котором снова будет показана вся страница и появится отчет

Ошибка в ответе AJAXec: SyntaxError: синтаксическая ошибка

Я думаю, что открытие дополнительного окна происходит из-за ошибки, но ошибка связана с ответом, имеющим весь html для всей страницы. На самом деле я не хочу никакой перезагрузки вызова ajax, если только у него нет определенного статуса.

Кроме того, последнее, что мне нужно сделать, это перезагрузить только одно представление на странице для конкретной истории, которая была обновлена.

Я пытался создать массив и добавить к нему короткие переменные, например, при первой загрузке страницы

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

и затем в блоке if во время обработки GET, чтобы вызвать его

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

, но не получается с ошибкой

Ошибка в ответе AJAXec: ошибка синтаксиса: отсутствует; до заявления Фатальная ошибка: вызов функции-члена js () для необъекта в C: \ wamp \ www \ paperless \ page \ scrumwall.php в строке 247


Окончательное обновление

Последняя ошибка вызвана тем, что я не использовал идентификатор для внешнего div всего представления, которое я хотел обновить.После того, как я изменил это значение, оно больше не равно нулю.

Итак, при первой загрузке страницы я сохраняю все имена представлений в ассоциативном массиве в цикле, помещая их на страницу

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

Обратите внимание, что если я хочу обновить только одно представление на странице, я могу просто вызвать этот объект chaing с перезагрузкой и выполнить, например:

$ pl-> js () -> reload () -> execute

, но если я хочу обновить несколько представлений на странице, мне нужно поместить их в массив (здесь он называется js[]) и затем вызовите execute следующим образом - вы также можете увидеть пример этого в примере кодовой панели Романа.

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

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

Проблема решена с помощью ATK4:)

Ответы [ 2 ]

1 голос
/ 30 сентября 2011

Хорошо, для более чистого ответа я собрал образец:

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

Вероятно, пример здесь лучше отвечает на вопрос.

В вашем случае, поскольку вы работаете с моделями, это должно быть легче настроить. Для представления я решил использовать 2 списка, но теоретически вы также можете рассматривать каждого человека и задачу в качестве представления.

Я храню ассоциации в сессии (через запоминание), в вашем случае вы бы сохранили их в базе данных.

1 голос
/ 30 сентября 2011

Ваша структура в порядке.Если вы используете 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();
}

Обычно, чтобы сделать ваш код универсальным, вы можете оставить этот код выше в представлении, но вместо «а» вам лучше использовать имя объекта, напримерэтот.Это устраняет необходимость в отдельном обновлении обработки страницы:

$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.Все они определяют 1-й аргумент js, такой как js (true), js ('click').в моем коде у меня есть js ('click'), поэтому он отправляется в браузер.
  3. Пользователь выполняет такие действия, как нажатие кнопки.Это вызывает функцию ajaxec ()
  4. Функция ajaxec выполняет AJAX-запрос к странице с аргументами, которые вы там указали.
  5. PHP снова выполняется, но на этот раз он идет внутрь ветви if ().Js () без аргумента создается и -> execute () отправляет JavaScript в браузер.
  6. браузер получает вывод js () ...-> execute () и оценивает его.В нашем случае он содержит reload () для какого-то другого элемента.
  7. Виджет atk4_loader используется для перезагрузки другой части страницы, он отправляет AJAX-запрос на сервер
  8. PHP выполняется с аргументом cut_object,Он повторно инициализирует исходную страницу, но выборочно отображает только один объект.Выходные данные для этого объекта отправляются обратно во внешний интерфейс.
  9. PHP также повторно генерирует JS-цепочки, как в # 2, но относится только к этому объекту
  10. atk4_loader фронтэнда получает код, заменяет HTML-кодэлемент и повторно оценивает JavaScript.
  11. вернуться к # 3

Звучит как множество действий.На самом деле это 2 запроса на клик, и вы можете отменить один, если перезагрузите сразу.Обратите внимание, что вы также можете передавать аргументы в reload (), которые затем можно получить из "get".Я не до конца понимаю, что вызывает действие в вашем оригинальном сценарии, возможно, мы можем узнать это в http://chat.stackoverflow.com/rooms/2966/agile-toolkit-atk4?

...