PLEASE NOTE: I'm not getting any errors, just not functioning the way my logic says it should.
I'm attempting to create a calendar application, essentially my goal at this stage, is on the $document.load of the calendar page, I wish for it to loop through each day of the calendar (1 month) and for each day, send a request to PHP (AJAX, $.post()), query database, and then append those results onto the element it is currently accessing with the.each() function.
What I want/expect to happen:
I expect the results that are passed back from PHP to be appended onto the current day element it is posting off for.
What does happen:
Unfortunately what seems to be happening, is that the post is done for each element (day in the month) but the append, is only happening once and appending to the last element in the set, although as you can see below, my.append is inside the.each()
Please help guys, I'm not sure how I can make it pause after each post and append to the current element, instead of the last!
CODE LISTING:
HTML:
<ul class="days">
<li><span>1</span></li>
<li><span>2</span></li>
<li><span>3</span></li>
<li><span>4</span></li>
<li><span>5</span></li>
<li><span>6</span></li>
<li><span>7</span></li>
<li><span>8</span></li>
<li><span>9</span></li>
<li><span class="active">10</span></li>
<li><span>11</span></li>
<li><span>12</span></li>
<li><span>13</span></li>
<li><span>14</span></li>
<li><span>15</span></li>
<li><span>16</span></li>
<li><span>17</span></li>
<li><span>18</span></li>
<li><span>19</span></li>
<li><span>20</span></li>
<li><span>21</span></li>
<li><span>22</span></li>
<li><span>23</span></li>
<li><span>24</span></li>
<li><span>25</span></li>
<li><span>26</span></li>
<li><span>27</span></li>
<li><span>28</span></li>
<li><span>29</span></li>
<li><span>30</span></li>
<li><span>31</span></li>
</ul>
jQuery:
$(".days li").each(function()
{
$dayNumber = $(this).text();
$this = $(this);
$.post("getShiftsMV.php", {dayNumber:$dayNumber}, function(results)
{
$this.append(results);
});
});
PHP:
$shifts = 0;
if($_POST["dayNumber"] != "" )
{
$day = $_POST['dayNumber'];
$sql = "SELECT * FROM shifts WHERE shift_date = '$day'";
$run = $con->query($sql);
if($run->num_rows > 0)
{
while($row = $run->fetch_assoc())
{
$shifts++;
}
}
if($shifts > 0)
{
echo'<span class="label label-success">' . $shifts .'</span>';
}
else
{
echo'';
}
}
=========================================================================
EDIT:
Using $var = "test"; for example, does work, as it will run in the console just fine.
Related
This is the div that i am updating
but i want to add a active class to the (li) item
every time the div refreshes the active class goes away
so i don`t want to refresh all the data in the (ul) but
only add (li) if there is a new data in the database,
with out refreshing the previous (li) items
<div id="contacts">
<ul id="rooms" class="rooms">
<!-- This is where the data get inserted -->
<!-- the ajax call and this -->
<li class='contact' data-val='<?php echo $room['id']; ?>'>
<div class='wrap'>
<div class='meta'>
<p class='name'><?php echo $room['sender']; ?></p>
<p class='preview'><?php echo $room['senderemail']; ?></p>
</div>
</div>
</li>
</ul>
</div>
this is my ajax call
$(document).ready(function() {
var interval = setInterval(function(){
$.ajax({
url: 'rooms.php',
success: function(data){
$('#rooms').html(data);
}
});
}, 1000);
});
in the room php
$rooms = get_rooms();
foreach($rooms as $room){
?>
<li class='contact' data-val='<?php echo $room['id']; ?>'>
<div class='wrap'>
<div class='meta'>
<p class='name'><?php echo $room['sender']; ?></p>
<p class='preview'><?php echo $room['senderemail']; ?></p>
</div>
</div>
</li>
<?php
}
the get_rooms() function
function get_rooms() {
$sql = "SELECT id, sender, senderemail FROM chatroom ";
$result = mysqli_query($GLOBALS['dbh'], $sql);
$rooms = array();
while($room = mysqli_fetch_assoc($result)){
$rooms[] = array('id'=>$room['id'], 'sender'=>$room['sender'],
'senderemail'=>$room['senderemail']);
}
return $rooms;
}
You Just need to push new data to the div as below just replace your line with:
$('#rooms').append(data);
this will add new <li> in your existing <div> after the last <li>
jquery append()
To get the id of the last <li>
var lastId = $( "#rooms li" ).last().attr('id');
Once you get the last id then pass it in your ajax call.
If I understand you correctly, your problem is that you lose the active class (which you clicked on the li container) when there is new data.
This has to do with the fact that you exchange all of the content.
There are now three options. Either
You give the rooms.php the id of the currently active li-container
and this script sets the active class for the affected container.
You transfer all the chatrooms (ids) already shown to rooms.php and only
load the new ones (this means effort later with sorting).
You save the active li class and re set it after content changed (this is the fastest)
f.e: in your Ajax succes functions:
let id=0;
let active_li = $('li.active');
if (active_li.length>0) id=active_li.data('val');
$('#rooms').html(data);
if (id!=0) $('li[data-val="'+id+'"]').addClass ('active');
A few other thoughts:
Note the interval of 1000ms. Possible it makes Problems if the request lasts longer than 1000ms. This may still work well in your tests, but maybe not anymore if there are a hundred or 1000 users in your application.
Doesn't it make sense to tell the server when you click the active room and save it in a session so that the server knows which room is active in the client?
You need to simply update your JS code like:
$(document).ready(function() {
var active_list = '';
var interval = setInterval(function(){
$.ajax({
url: 'rooms.php',
beforeSend: function(){
active_list = $('#rooms').find('li.contact.active').attr('data-val');
}
success: function(data){
$('#rooms').html(data);
$(data).find('li[data-val="' + active_list +'"]').addClass('active');
}
});
}, 1000);
});
This should solve your problem and Let me know if you still face any issue.
I'm using Laravel 5.5.* and jQuery (jquery-3.3.1.min.js).
I commercially develop mostly (like 95% of the time) in PHP, so using jQuery is really different for me, so I need help.
I am developing a blog's landing page and I must show just 3 posts in it. In it's bottom, I have a button <a> that is supposed to load 3 more posts and show it to the user. Everytime the user hits this button, 3 more posts must load in the page.
I have the following codes so far.
Posts controller
public function index() {
// this loads the landing page with 3 initial posts
// Working like a charm
$posts = Posts::with('categories', 'user', 'media')
->where('status', 1)
->orderBy('published', 'desc')
->limit(3)
->get();
$rank = self::blogPanel();
return view('portal.pages.blog',
compact(
'rank',
'posts'
)
);
}
I call this action from the route
Route::get('/', 'User\PostsController#index')->name('landingPage');
For the logic in which I load more posts, I have the following:
Posts Controller
public function loadMore() {
$posts = Post::with('categories', 'user', 'media')
->where('status', 1)
->orderBy('publicacao', 'desc')
// ->limit(3) I took this out because I was trying to set the limit in front-end
->get();
return json_decode($posts);
}
Which returns the following:
array:48 [▼
0 => {#257 ▼
+"id": 48
+"title": "Lorem ipsum"
+"summary": "Perferendis labore veritatis voluptas et vero libero fuga qui sapiente maiores animi laborum similique sunt magni voluptate et."
+"content": """
Really long text here, with line-breaks and all
"""
+"seo_id": null
+"url": "Sunt rerum nisi non dolores."
+"link_title": "dolor"
+"published": "2018-03-01 10:35:12"
+"scheduled": "2018-03-01 10:25:12"
+"user_id": 1
+"media_id": null
+"status": 1
+"created_at": "2018-03-01 10:25:12"
+"updated_at": "2018-03-01 10:25:12"
+"category_id": 3
+"slug": "cum-aut-officia-consequatur-dolor"
+"categories": []
+"user": {#313 ▼
+"id": 1
+"name": "Jonessy"
+"email": "jonessy#email.com"
+"status": 1
+"grupo_id": 1
+"created_at": null
+"updated_at": null
}
+"media": null
}
1 => {#341 ▶}
2 => {#254 ▶}
]
Please, note I'm using json_decode() because it looks easier to work with in front-end.
This is my blade file, where I should print my results
blogPost.blade.php
#foreach($posts as $post)
#php
$date = date_create($post->published);
#endphp
<div class="blog-post" id="blog-post">
<div class="blog-post__title" >
<h3 id="artTitle">
{{ $post->title }}
</h3>
#foreach($post->categories as $cat)
<span class="blog-post__category"> {{ $cat->name }} </span>
#endforeach
<span class="blog-post__date" id="artDate">
{{ date_format($date,"d/m/y - H") }}H
</span>
</div>
<div class="blog-post__image" id="artImage">
#if(isset($post->media_id))
<img src="{{ asset('img/post-img/' . $post->media->file) }}">
#else
<img src="{{asset('img/post-img/default-img-post.jpg')}}">
#endif
</div>
<div class="blog-post__resume">
<p id="artSumma">
{{ $post->summary }}
</p>
</div>
<div class="blog-post__link">
<a href="{{ route('blogPost', $post->slug) }}">
Read More
</a>
</div>
<div class="blog-post__social">
// Some social media links for sharing
</div>
</div>
#endforeach
I am calling the loadMore() method from PostsController using a GET route:
Route::get('/', 'User\PostsController#loadMore')->name('loadMore');
For jQuery, here is the code I got so far:
<script type="text/javascript">
// after importing jquery file...
$(document).on('click', '#loadingPosts', function(e) {
e.preventDefault();
var listing = {!! $posts !!};
console.log("list ", listing);
var lastId = listing[2].id;
console.log("id from pos 2, listing ", lastId);
var parts = $(listing).slice(lastId);
console.log("part ", parts);
// THIS DOESN'T WORK, BY THE WAY
// var lastId = listing[2].id;
// console.log("listing 2 id", lastId);
$('#loadingPosts').html("Loading More Posts");
$.ajax({
url: '{{ route('loadMore') }}',
method: 'GET',
// data: {
// 'id': lastId,
// I was trying to set up an ID here, but it didn't work as well
// },
// contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
// console.log("checking if data not null", data);
// this returns the expected $posts array
$('#blog-post').html(data);
// using .html() because .append() didn't work, which is weird, I guess
console.log("data depois do apend", data);
// This returns the same $posts array
lastId = data[2].id;
console.log("last id from data", lastId);
// I can retrieve the id from the given position from the array.
// I was trying to set up the id here so I could check, with jQuery, the last post iterated, so I could continue from that point forward
$('#loadingPosts').html("load More");
return data[2].id;
// A last minute despair
}
});
});
</script>
Well, it doesn't work (that's the reason I'm here). I really don't know what I am doing wrong, since the $posts array is passing...
I need help with this, please.
A few things worth saying:
Laravel comes with a default pagination, but it works "horizontally", and the projects asks for a "vertical" pagination.
The page must have a "load more" button because the footer has some much needed info, so the content can not load automatically
IF there is a way to make it work using vanilla JavaScript OR using Laravel's PHP methods (EXCEPT FOR THE PAGINATION METHOD, AS STATED BEFORE), I would be really happy
Thank you all in advance.
public function loadMore(Request $request) {
$posts = Post::with('categories', 'user', 'media')
->where('status', 1)
->orderBy('publicacao', 'desc')
->limit($request->input('limit'))
->skip($request->input('skip'))
->get();
return json_decode($posts);
}
But you can just use the next page from pagination()
So, after a little while I came up with a fix for my needs.
Turns out I didn't need to json_encode() or json_decode() anything.
First of all, I'll use a pseudo mark-up for everything inside blades. It'll be easy to understand, since what I am using is HTML. For jQuery, someone involved with the project came up with a pseudo-jQuery-like functions that emulate its syntax. It is a straight forward syntax, easy to understand, nothing out of the ordinary.
Then, here it is.
PostsController
public function loadMore(Request $request) {
$limit = $request->input('limit');
$skip = $request->input('skip');
// as #Dry7 suggested, I am taking a dynamic skip
$posts = Post::with('categories', 'user', 'media')
->where('status', 1)
->orderBy('published', 'desc')
->limit($limit)
->skip($skip)
->get();
return view(
'portal.pages.blogPost',
compact(
'posts'
)
)->render(); // here is the difference
}
So, what I did is pre-render the view where the posts will be printed WITHOUT loading a new page.
Before we continue, here is the structure of the blog.(Using pseudo-markup, as stated before)
main page
#extends('layouts.layout')
div class=container
div class=blog
h1
Page title
/h1
div class=blog-body
#include('portal.pages.blogPost')
a id=loadMorePosts class=none
Load More
/a
/div
div class=sidebar
#include('portal.components.panel')
/div
/div
/div
Then in my pages.blogPost I have the same code I posted in my question (The code is the one with the foreach loop).
After this, I came up with this pseudo-jQuery-like code.
// I'll start listening to any 'click' in the element I am passing the event
// then I'll increment the number of clicks in the element
var click = 0;
// this is the first skip number
var startCounting = 6;
// start a click event in the <a #loadMorePosts> element
$.event('#loadMorePosts','click',function () {
// increment the number of clicks
click++;
// set my skip that will be sent to server and
// applied in my PostsController
skip = startCounting * click;
// open an ajax request passing the route I set up
// that calls PostsController#loadMore method
HttpRequest.get('{{ route('loadPosts') }}?limit=6&skip=' + skip,function (res) {
// I am concatenating my skip var here, so It'll be sent to server
// checking if I have an empty data
if(res.data != "") {
// not empty, so I'll append it to my div with blog class
// first finding the element, searching for its class
// then passing the data to be appended
$.append('.blog',res.data);
} else {
// the data is empty, so first I'll search for
// the element with class=none
// clean up any innerHtml it has
// then set up a new innerHtml in it
$.replaceAll('.none',"No More Posts");
// to finish it all up, I style the same element with some suggesting colors and actions
$.css('.none', 'pointer-events: none; background-color: lightgrey;');
}
});
});
And its done. The posts are appended, the skip is working, so I don't take repeated posts, it works until all of my posts are loaded and when there are no more posts to show, the button is disabled, stopping any new request to be sent to server.
I hope that with these comments the process made to implement this functionality is clear and you can apply the same steps with whatever framework or library you are using.
Thank you all for reading and for taking time to answer my question.
I am trying to find the order of the items as they are dragged over to the new column. I am updating the column that the item lives in once its dragged over with AJAX. I am also getting everything in order with $(this).sortable('serialize'). when I put that into an alert. The problem I am having though is when I send the array to PHP, one of the items gets dropped in the list. I am guessing it has something to do with the way I am using serialize but I am not sure. Any help I can get would be greatly appreciated. Co-workers tell me I should just accept the limits of the code and live with it. I disagree and know that the order the item is placed is almost as important as what column the data lives in. I'm thinking I need two different events in the javascript. One for the drag between lists and one in case the user rearranges items that are in the div. Hoping someone can point me in the right direction.
The HTML I have
<div class="col-lg-12 text-center">
<div class="col-md-3">
<h3>Unsorted Items</h3>
<ul id="UNSORTED" class="connectedSortable">
<li id="item-1">Unsorted item 1 from DB</li>
<li id="item-2">Unsorted item 2 from DB</li>
<li id="item-3">Unsorted item 3 from DB</li>
<li id="item-4">Unsorted item 4 from DB</li>
<li id="item-5">Unsorted item 5 from DB</li>
</ul>
</div>
<div class="col-md-3">
<h3>ACCEPTED</h3>
<ul id="ACCEPTED" class="connectedSortable">
<li id="item-6">Unsorted item 6 from DB</li>
<li id="item-7">Unsorted item 7 from DB</li>
<li id="item-8">Unsorted item 8 from DB</li>
</ul>
</div>
<div class="col-md-3">
<h3>REJECTED</h3>
<ul id="REJECTED" class="connectedSortable">
<!-- empty to show drag to -->
</ul>
</div>
</div>
The Javascript
<script>
$(function() {
$( "#UNSORTED, #ACCEPTED, #REJECTED" ).sortable({
connectWith: ".connectedSortable",
receive: function(event, ui) {
// The position where the new item was dropped
var newIndex = ui.item.index();
var sender = ui.sender.context.id;
var receiver = this.id;
var idNum = ui.item.context.id;
var display_order = $(this).sortable('serialize');
//this alerts the correct order
alert(display_order);
//this when uncommented alerts what item tranfered to and from
//alert(idNum + ' Was Transfered from "' + sender + '" to "' + receiver + '".');
//this tell the new order of the items the item was dragged to
//alert(receiver + ' Order is ' + $(this).sortable('serialize'));
var action = 'update_selection';
$.ajax({
url: "index.php?action=" + action + "&item=" + idNum + "&selection=" + receiver + '&item-' + display_order,
success:function (data) {
$("#results").html(data).slideDown('2000');
}
});
},
stop: function (event, ui) {
var sender = this.id;
var data = $(this).sortable('serialize');
//this when uncommented alerts new order of old list
//alert(sender + ' Order is ' + data);
//this was to write new order of old list unless I can figure out how to write it in the 'receive' event
/*$.ajax({
data: oData,
type: 'POST',
url: '/your/url/here'
});*/
}
}).disableSelection();
});
</script>
Shortened version of PHP
$item_id = filter_input(INPUT_GET, 'item');
/*the number after item- is dynamic from the DB and I was unable to get serialize to work without the item- in it so now I am removing item- to get the actual DB id with preg_replace */
$item_id = preg_replace('/^item-/', '', $item_id);
$selection = filter_input(INPUT_GET, 'selection');
//can't use filter_input on an array
$display = $_GET['item'];
/*this dumps the array with an array item missing. Sometimes its the first item in the array and sometimes its not */
var_dump($display);
Okay I figured it out. I needed to pass the AJAX with POST and not GET. BUT, I was still having a problem with the way I was doing it because I cannot do it the way I was doing it. I was intending on having a table that just had the display orders for each column. But that's pretty dumb when in the item table there is already a column name that the item belongs to. Its easier to just add another column with display order that update whenever the item is moved to another column. So here is my full working code which updates with AJAX and remembers where in the new column the item was placed. If anyone ever comes across this post and knows a better way, please do share. I love learning from my mistakes.
The HTML
<div class="col-lg-12 text-center sortable">
<div class="col-md-3">
<h3>Unsorted Items</h3>
<!--I am not including the PHP loop to display the list of items -->
<ul id="UNSORTED" class="sort-list">
<li id="item-1">Unsorted item 1 from DB</li>
<li id="item-2">Unsorted item 2 from DB</li>
<li id="item-3">Unsorted item 3 from DB</li>
<li id="item-4">Unsorted item 4 from DB</li>
<li id="item-5">Unsorted item 5 from DB</li>
</ul>
</div>
<div class="col-md-3">
<h3>ACCEPTED</h3>
<ul id="ACCEPTED" class="sort-list">
<li id="item-6">Unsorted item 6 from DB</li>
<li id="item-7">Unsorted item 7 from DB</li>
<li id="item-8">Unsorted item 8 from DB</li>
</ul>
</div>
<div class="col-md-3">
<h3>REJECTED</h3>
<ul id="REJECTED" class="sort-list">
<!-- empty to show drag to -->
</ul>
</div>
</div>
The Javascript
<script>
$(function(){
/* Sort steps */
$('.container').sortable({
axis: "y",
update: function (event, ui) {
var data = $(this).sortable('toArray');
$("#result").html("JSON:<pre>"+JSON.stringify(data)+"</pre>");
}
});
/* Here we will store all data */
var myArguments = {};
function assembleData(object,arguments)
{
var data = $(object).sortable('toArray'); // Get array data
var step_id = $(object).attr("id"); // Get step_id and we will use it as property name
var arrayLength = data.length; // no need to explain
/* Create step_id property if it does not exist */
if(!arguments.hasOwnProperty(step_id))
{
arguments[step_id] = new Array();
}
/* Loop through all items */
for (var i = 0; i < arrayLength; i++)
{
var image_id = data[i];
/* push all image_id onto property step_id (which is an array) */
arguments[step_id].push(image_id);
}
return arguments;
}
/* Sort images */
$('.sort-list').sortable({
connectWith: '.sort-list',
//leaves out the bootstrap class
items : ':not(.col-md-3)',
/* That's fired first */
start : function( event, ui ) {
myArguments = {}; /* Reset the array*/
},
/* That's fired second */
remove : function( event, ui ) {
/* Get array of items in the list where we removed the item */
myArguments = assembleData(this,myArguments);
},
/* That's fired thrird */
receive : function( event, ui ) {
/* Get array of items where we added a new item */
myArguments = assembleData(this,myArguments);
},
update: function(e,ui) {
if (this === ui.item.parent()[0]) {
/* In case the change occures in the same container */
if (ui.sender == null) {
myArguments = assembleData(this,myArguments);
}
}
},
/* That's fired last */
stop : function( event, ui ) {
/* Send JSON to the server */
var action = 'update_selection';
var orders = JSON.stringify(myArguments);
$.ajax({
url: 'index.php',
type: 'POST',
data: {action: action, code: orders},
//I used success function to var_dump PHP when testing
success:function (data) {
$("#result").html(data).slideDown('2000');
}
});
}
});
});
</script>
and last but not least the PHP file. I use MVC so I am calling the action and sending my script to the right case to process the PHP (Just in case someone reading this is unaware I will include that whole PHP file.)
require("classes/Db.class.php");
$db = new Db();
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else if (isset($_GET['action'])) {
$action = $_GET['action'];
} else {
$action = 'home';
}
switch ($action) {
case 'home':
//gets all items and display order for those items
$unsorted = $db->query("SELECT * FROM sorting WHERE column_name = 'UNSORTED' ORDER BY display_order");
$accepted = $db->query("SELECT * FROM sorting WHERE column_name = 'ACCEPTED' ORDER BY display_order");
$rejected = $db->query("SELECT * FROM sorting WHERE column_name = 'REJECTED' ORDER BY display_order");
$possible = $db->query("SELECT * FROM sorting WHERE column_name = 'POSSIBLE' ORDER BY display_order");
include_once('home.php');
break;
case 'update_selection':
$json = filter_input(INPUT_POST, 'code'); //gets the json stringify
$array = json_decode($json, true); //specify an associative array instead of an object from json_decode
foreach($array as $key => $value){
//gets column item belongs to now
$column_name = $key;
foreach($value as $key => $number){
//this gets the key which we will use for ordering
$order = $key;
//update DB with column name item belongs to and the new order of all items in that column
$db->query("UPDATE sorting SET column_name = :column_name, display_order = :order WHERE gun_id = :number", array("column_name"=>$column_name, "number"=>$number, "order" => $order));
}
}
break;
im trying to learn Angular.
Here is what im trying to do:
I am building an App that shows me citys. When i click on a city i want to see a list of all my favourite citys.
Using an "Show-List" Button with ng-click works but requires the button the be pushed.
Here is my approach for getting it done automatic:
I want a list in my DOM automatically updated on change of the list.
$scope.$watch('updatedList', function() {
// CHECK IF WORKS
console.log($scope.updatedList);
// APPLY TO DOM
$timeout(function(){
$scope.$apply(function () {
$scope.watchList = $scope.updatedList;
});
}, 1000)
});
The Console shows no error and gives out the correc values:
Object {city.3: "Herat", city.7: "Haag", city.10: "Tilburg" ......}
In my div is the following:
<ul>
<li ng-repeat="y in updatedList">{{ y }}</li>
</ul>
<ul>
<li ng-repeat="a in watchList">{{ a }}</li>
</ul>
First for the NG-Click-Version(which works on click) second for the $scope.$watch
Sorry for lots of questions but im really struggling with the Angular-Docs.
EDIT:
Function that Adds Citys to the List:
$scope.addToList = function(name,id) {
var cityToAdd = name;
var cityToAddID = id;
// ADD A CITY TO THE COOKIE -> WORKS
$cookies.put('city.' + cityToAddID, cityToAdd);
$scope.newList = $cookies.getAll();
$scope.addToListMessage = cityToAdd + " wurde hinzugefügt";
// Show short INFONOTICE
window.setTimeout(function() {
$scope.$apply(function() {
$scope.addToListMessage = "";
});
}, 1000);
// Update the List
$scope.updateList();
};
Second Functions -> gets Values from Cookies and puts them to an Array:
$scope.updateList = function() {
var allCitys = $cookies.getAll();
// PUT ALL INTO AN ARRAY -> WORKS
var favouritesFromCookie = [];
$.each(allCitys, function(index, value) {
if (index.indexOf('city.') == 0) { favouritesFromCookie.push(value) }
});
// PUT THE ARRAY OF CITYS INTO A SCOPE_VARIABLE
$scope.updatedList = favouritesFromCookie;
};
Your $scope.updatedList needs to be an array to be used in ng-repeat.
You shouldn't directly write a list in expression. Try this
<ul>
<li ng-repeat="y in watchList">{{ y.city }}</li>
<li ng-repeat="y in watchList">{{ y.yourListItem}}</li>
</ul>
I have three db tables.
-Paid
-Partially Paid
-Owes
When someone registers for an account I send their user_id, name, etc to my 'Owes' db table and then output their name into a drag and drop table I have in the 'Owes' column. As of now if I move anyone's name to any other category (Paid/Partially paid) I am not sure how to delete that record from the Owes db and insert the name into the new db table so the changes are permanent.
What's really throwing me off is how to do it with the drag and drop table. I'm not sure how to apply the logic that when something is dropped into that column that the past record is deleted and a new one is added to that specific table or how to make the changes without a submit button or page reload.
What is a way I can do this and how could I structure it?
PHP
<?php
//Payment Section
$con = mysqli_connect("localhost", "root", "", "db");
$paid_run = mysqli_query($con,"SELECT * FROM paid ORDER BY id DESC");
$partially_paid_run = mysqli_query($con,"SELECT * FROM partial_payment ORDER BY id DESC");
$owes_run = mysqli_query($con,"SELECT * FROM owes ORDER BY id DESC");
$paid_numrows = mysqli_num_rows($paid_run);
$partially_paid_numrows = mysqli_num_rows($partially_paid_run);
$owes_numrows = mysqli_num_rows($owes_run);
if($paid_numrows > 0){
while($row = mysqli_fetch_assoc($paid_run)){
$paid_id = $row['user_id'];
$paid_name = $row['name'];
}
}
if($partially_paid_numrows > 0){
while($row = mysqli_fetch_assoc($partially_paid_run)){
$partially_paid_id = $row['user_id'];
$partially_paid_name = $row['name'];
$partially_paid_amount = $row['payment'];
}
}
if($owes_numrows > 0){
while($row = mysqli_fetch_assoc($owes_run)){
$owes_id = $row['user_id'];
$owes_name = $row['name'];
}
}
?>
$(function() {
$( "#paid, #partially_paid, #owes" ).sortable({
connectWith: ".tdPayment",
remove: function(e, ui) {
var $this = $(this);
var childs = $this.find('div');
if (childs.length === 0) {
$this.text("Nothing");
}
},
receive: function(e, ui) {
$(this).contents().filter(function() {
return this.nodeType == 3; //Node.TEXT_NODE
}).remove();
},
}).disableSelection();
});
Table
<table class="paymentTable" id="dragTable">
<tr>
<th class="thPayment">Paid</th>
<th class="thPayment">Partially Paid</th>
<th class="thPayment">Owes</th>
</tr>
<tr>
<td class="tdPayment" id="paid">
<div>
<?php
if ($paid_name == true) {
echo $paid_name;
} else {
echo "No one has paid";
}
?>
</div>
</td>
<td class="tdPayment" id="partially_paid">
<div>
<?php
if ($partially_paid__name == true) {
echo $partially_paid__name . " - " . $partially_paid_amount;
} else {
echo "No one has made a partial payment";
}
?>
</div>
</td>
<td class="tdPayment" id="owes">
<div>
<?php
if ($owes_name == true) {
echo $owes_name;
} else {
echo "Everyone has paid something";
}
?>
</div>
</td>
</tr>
</table>
Here's a rough outline on how to do it. I would recommend using jQuery, a JavaScript library that has a lot of useful stuff for this.
Implement the drag and drop part using jQuery draggable and droppable. A nice guide can be found here.
Write a PHP page that updates the database the way you want it.
Use jQuery to call that page when something is dropped. This can be done using Ajax.
Clarification of part 3
I recommend looking at the photo manager in the droppable documentation to get a full working example of something similar.
For this to work, you need to set up the HTML so it has some class names and some data attributes:
<h1>Owes</h1>
<div class="bin" data-bin-id="1">
<div class="user" data-user-id="5">Eva</a>
<div class="user" data-user-id="8">Anna</a>
</div>
<h1>Partially paid</h1>
<div class="bin" data-bin-id="2">
<div class="user" data-user-id="2">Tom</a>
...
</div>
...
Then we need to implement some javascript that takes care of calling the PHP when the user drops something:
jQuery(".bin").droppable({
accept: ".user",
drop: function( event, ui ) {
//Get the ID of the bin the user was dropped into.
var intBinID = jQuery(this).attr("data-bin-id");
//Get the ID of the user that was dropped.
var intUserID = ui.droppable.attr("data-user-id");
//Make an ajax call to the PHP page.
jQuery.ajax("update.php?binid=" + intBinID + "&userid=" + intUserID);
}
});
In addition you might want update.php to return something to let the JavaScript know if it worked or not, and if it failed abort the drop.
Disclaimar: Since I don't have all the parts of this project set up, I have not tested this code.
An easier way to do this, is by creating an independent User table where you keep all the users. Then, in a separate table like the ones you have already, you just keep the Id of that user (and maybe some information related to how much he owes or has already payed).
This way, when you have to insert or to update any information about the state of the user, you just have to insert/delete the Id of the User from these tables.
The information about the user will always be safe and kept in it's own table.