Note that there are some explanatory texts on larger screens.

plurals
  1. POin atk4, how do i use ajax to update a view
    primarykey
    data
    text
    <p>I currently have a page defined which displays some data in rows. At the end of each row, there is a view which shows a total which is extracted from mysql.</p> <pre><code>$r-&gt;add('View_PointsLeft', 'pleft', 'pointsleft') -&gt;setPoints($row['points_left']) -&gt;setBacklog($row['backlog_ref']) -&gt;setID($row['id'].'-points-left'); </code></pre> <p>The view is defined with a template like this</p> <pre><code>&lt;!-- points left --&gt; &lt;div class='target points_left'&gt; &lt;div class='sticky green'&gt; &lt;div class='story'&gt;&lt;?$backlog?&gt;&lt;/div&gt; &lt;div id='&lt;?$name?&gt;' class='big_points big_point_margin'&gt;&lt;?$pointsleft?&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;!-- end 0000-points-left --&gt; </code></pre> <p>The data to populate the view is selected using a sql in the page which is looped through and the /lib/view/pointsleft.php code has set methods which are passed parameters from the page and update the fields in the template.</p> <p> <pre><code>class View_PointsLeft extends View_Sticky { function init(){ parent::init(); } function setPoints($points){ $this-&gt;template-&gt;set('pointsleft',$points); return $this; } function setBacklog($backlog){ $this-&gt;template-&gt;set('backlog',$backlog); return $this; } function defaultTemplate(){ return array('view/scrumwall/pointsleft'); } } </code></pre> <p>I want to update the database when something is changed on the page and also update the total view (to decrement the counter).</p> <p>First, I'm wondering if i have approached this the wrong way (should each view should be self contained) - should i just pass the id field to the view, attach the relevant model to the view inside lib/view/pointsleft.php and call the set fields using the model values ?</p> <p>Secondly, If i change it that way, does it then make it easier to update the view with a particular id when the database value is changed using ajax and if so , how do i do this ? </p> <p>Thirdly - if i want to also trigger an update into the database based on an action on the client side javascript, where would i put this code e.g. in the non atk4 version of my code, i had a script called using $.post("update.php") which would update mysql. Where would i put such a script in ATK4 ? </p> <p>Thanks in advance.</p> <hr> <p><strong>Update after answer from Romans</strong></p> <p>Man, ATK4 rocks ! - it does more than i expected and i was busy creating functions inside the view to populate each field name, so now having redone it using addModel, </p> <p>the call from the page looks like this</p> <pre><code> $r-&gt;add('View_PointsLeft', 'pleft', 'pointsleft') -&gt;loadData($row['id']); </code></pre> <p>the templates/view looks like this</p> <pre><code>&lt;div id='&lt;?$name?&gt;' class='target points_left'&gt; &lt;div class='sticky green'&gt; &lt;div class='story'&gt;&lt;?$backlog_ref?&gt;&lt;/div&gt; &lt;div class='big_points big_point_margin'&gt;&lt;?$points_left?&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <p>and the lib/view code looks like this</p> <pre><code>&lt;?php class View_PointsLeft extends View_Sticky { function loadData($id){ $this-&gt;setModel('Story')-&gt;loadData($id); } function init(){ parent::init(); } function defaultTemplate(){ return array('view/scrumwall/pointsleft'); } } </code></pre> <hr> <p><strong>Update after code example from Romans</strong></p> <p>After following the code example Romans provided, i now add the URL call using jquery selectors at the bottom of my page code and do some jiggery pokery to get the task and status from the id fields (not sure about using HTML5 only stufff using data-id so just set the normal id and extract from that). Previously the drop code was in my own univ.js script but i dont have access to the php variables from there so i move it into the page</p> <pre><code> $p-&gt;js(true)-&gt;_selector('.movable')-&gt;draggable(); $p-&gt;js(true)-&gt;_selector('.target')-&gt;droppable(array( 'drop'=&gt;$this-&gt;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-&gt;api-&gt;getDestinationURL().'",'. 'task: task, status: newStatus }); } ') )); </code></pre> <p>and i have a if block which looks like this in the page. I add Model_Task and load the values based on the GET parameter so i then also have more information including the story it relates to so i can also update the points if the status is now done. </p> <pre><code> if($_GET['task'] &amp;&amp; $_GET['status']) { $new_status=$_GET['status']; $task_id=$_GET['task']; $t=$p-&gt;add('Model_Task')-&gt;loadData($task_id); $old_status=$t-&gt;get('status'); $task_points=$t-&gt;get('points'); if ($new_status&lt;&gt;$old_status &amp; ($new_status=='D' | $old_status=='D')) { $s=$p-&gt;add('Model_Story')-&gt;loadData($t-&gt;get('story_id')); if ($old_status='D') { $s-&gt;set('points_left',$s-&gt;get('points_left')+$task_points); } else { $s-&gt;set('points_left',$s-&gt;get('points_left')-$task_points); } $s-&gt;update(); $story=$t-&gt;get('story_id'); } $t-&gt;set('status',$new_status); $t-&gt;update(); } </code></pre> <p>i can then calculate the new number of points and update the story with points left and update the task with the new_status by setting the model values and using update().</p> <p>If i now move one of the draggables, it works but opens a new window showing again the whole page and reporting </p> <p><strong>Error in AJAXec response: SyntaxError: syntax error</strong></p> <p>I think opening the extra window is because of the error but the error is something to do with the response having all the html for the whole page. I dont actually want any reload from the ajax call unless the status is a particular one.</p> <p>Also the last thing i need to do is only reload one view on the page for the particular story that was updated.</p> <p>I've tried by creating an array and adding the short variables to it like this when the page is first loaded</p> <pre><code> $this-&gt;pl_arr[$row['id']]=$r-&gt;add('View_PointsLeft', 'pleft', 'pointsleft') -&gt;loadData($row['id']); </code></pre> <p>and then in the if block while processing the GET, to recall it</p> <pre><code> $pleft=$this-&gt;pl_arr[$story]; $pleft-&gt;js()-&gt;reload()-&gt;execute(); </code></pre> <p>but it fails with an error </p> <p><strong>Error in AJAXec response: SyntaxError: missing ; before statement Fatal error: Call to a member function js() on a non-object in C:\wamp\www\paperless\page\scrumwall.php on line 247</strong></p> <hr> <p><strong>Final update</strong> </p> <p>The last error is caused because i didnt use for the id in the outer div of the whole view i wanted to update. Once i changed this it is no longer null.</p> <p>So the first time the page is loaded, i store all the view names in an associative array in a loop as i put them on the page</p> <pre><code> $st = $p-&gt;add('Model_Story'); $result = $st-&gt;getRows(); foreach ($result as $row) { if (is_array($row)) { $r=$p-&gt;add('View_Scrumwall_StoryRow') -&gt;setWorkspace('ws-'.$row['id']); ... other code here ... $points_left[$row['id']]=$r-&gt;add('View_PointsLeft', null, 'pointsleft') -&gt;loadData($row['id']); } </code></pre> <p>and then have the if GET block like this </p> <pre><code> if($_GET['task'] &amp;&amp; $_GET['status']) { $new_status=$_GET['status']; $task_id=$_GET['task']; $t=$p-&gt;add('Model_Task')-&gt;loadData($task_id); $old_status=$t-&gt;get('status'); $task_points=$t-&gt;get('points'); if ($new_status&lt;&gt;$old_status &amp;&amp; ($new_status=='D' || $old_status=='D')) { $s=$p-&gt;add('Model_Story')-&gt;loadData($t-&gt;get('story_id')); if ($new_status=='D') { $s-&gt;set('points_left',$s-&gt;get('points_left')-$task_points); } else { $s-&gt;set('points_left',$s-&gt;get('points_left')+$task_points); } $s-&gt;update(); $story=$t-&gt;get('story_id'); //reload the points left sticky note for the story of the task $js[]=$points_left[$story]-&gt;js()-&gt;reload(); } $t-&gt;set('status',$new_status); $t-&gt;update(); $js[]=$this-&gt;js()-&gt;reload(); $this-&gt;js(null,$js)-&gt;execute(); } </code></pre> <p>Note that if I only want to update one view on the page, i can just call that chaing that object with reload and execute e.g.</p> <p>$pl->js()->reload()->execute</p> <p>but if i want to update several views on the page, i need to put them in an array (here called js[]) and then call execute like this - you can also see an example of this in Roman's codepad example.</p> <pre><code> $js[]=$points_left[$story]-&gt;js()-&gt;reload(); $js[]=$this-&gt;js()-&gt;reload(); $this-&gt;js(null,$js)-&gt;execute(); </code></pre> <p>Problem solved with ATK4 :)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload