Laravel pagination using infinite scroll - ajax

Can anyone help me by pointing me in the right direction on how to implement an infinite scroll in Laravel?
I'm familiar with Laravel's pagination tool and I'm also familiar with Javascript.
I just can't figure out what should i send via ajax to my controller?
By that i mean what url parameters and how would that dynamically change on scrolling?
Thanks in advance.

you do not have to send via ajax something special
just grab via JS the id of last post which already have been loaded and perform ajax.get to http://example.com/foo/100500
catch id in routes.php something like this Route::get('foo/{id}', 'BazController#bar'
then perform any logic in your controller as you wish just considering the id
for example select from database where id between id and id+20
UPDATED
considering #ugochimbo 's question
Let's say when we GET our page first time, we obtain something like
<div id="container">
<div id="post-30">Lorem impum dolor</div>
<div id="post-29">Lorem impum dolor</div>
<div id="post-28">Lorem impum dolor</div>
</div>
An event is happened e.g. ( scrollTop is more than some px )
Then we execute something like
Hey, jQuery! Gimme "id" of the last child of the #container //it will
be "post-28"
Considering the id, we perform an ajax query to a server.
I assume that for the simpliest implementation of infinity scrolling, we have to know just the "id" on the client side, nothing else.
Of course, in any real cases there is also a bunch of additional information, such as DESC or ASC or whatever else. It's all up to you.
Let's say we obtained on the server side via ajax query
{lastLoadedPostId: 'post-28', order: 'DESC', postsPerQuery: 3}
Of course, we have to make some preparations e.g. Cut "post-" from "lastLoadedPostId" etc
Then we ask our database
Hey, database! Gimme 3 posts, that have id less than 28, in desc order
If nonIncremental identificators are used in your database, and you obtain on the server side
{lastLoadedPostId: 'qwertyuid', order: 'DESC', postsPerQuery: 3}
In that case you should perform one extra query to database
Hey, database! Tell me when "qwertyuid" was created
Hey, database! Gimme 3 posts that were created earlier than "timestamp
of qwertyuid"
For this purpose you may use commands like LIMIT, OFFSET or whatever your database provided, but it's already other question

Related

Form and availability of "formers"

I am stuck on a problem that I did not think before.
I have a form formers with 3 fields (name, firstname, status).
Then, my second form is the trainings with 2 fields (date_sitting, fk_former).
Here, I have 1 sitting date -> 16/07/2019 and the former is Dujardin Luc.
Now my problem is that if I want to create a new sitting for on 18/07/2019.
How to do for that the former Dujardin Luc to be available in my dropdownlist for on 18/07/2019 or another date??
Is it, in my case, I must to create 2 files create.blade ?
The first will just have a field -> date_sitting
And the second form will have the field -> fk_former ?
Here is my TrainingController for information
public function index()
{
$trainings = Training::oldest()->paginate(5);
$formersNoTrainingToday = Training::whereDate('date_sitting', "!=", Carbon::today())
->orWhere('date_sitting', null)->get();
$formers = Former::doesntHave('trainings')->get();
return view('admin.trainings.index', compact('trainings'))
->with('i', (request()->input('page',1) -1)*5);
}
I can't give you the whole answer, as there are too many things to update and a few things to decide.
First, you'll need to change your index() method to both send more and different data. If a former can train on multiple days, the $formers = Former::doesntHave('trainings')->get(); is no longer valid -- you want all formers now so that you can add a new date. So just $formers = Former::get(); now.
Next, your $formersNoTrainingToday is now obsolete, as you don't want to identify those who are unavailable just today, you want a list of all training dates so compare against whatever date the user is looking for in the form. Example: If Dujardin Luc wants training on 18/07/20XX, we don't want him in a list of NoTraining because we want him available, even if he is unavailable today.
Last on the controller side, depending on how you want to do the blade side, you might want to include a variable for an AJAX date to use to send through those formers who are available on the specific date requested by the user through AJAX. For example, if you go through AJAX, you might have a method to just send those available on the date requested like this in your controller (Not exact code):
public function getFormersWithoutTrainingOnDateRequested($dateRequested){
$formersAvailableToday = Training::whereDate('date_sitting', "!=", Carbon::createFromFormat('Y-m-d', $dateRequested))
->orWhere('date_sitting', null)->get();
return json_encode($formersAvailableToday);
}
The next part is on the blade side. You have quite a few choices here, but both of the ones I recommend involve some type of JS or Jquery. In order to populate the list of formers for the day that the user requests, for best user experience, you should get them the list quickly.
Fastest would be to provide a list of trainings (date_sitting, fk_former) to the page from the index. This would be stored as a data-object on some element of the blade page. Then, when the user clicks to change the date, a JS or Jquery function would pull the list into a var, compare it against another list of former's ids stored the same way, and re-write the select list immediately, using only those formers whose ids were not matched for the date.
Second way to do this would be a little slower, but a little easier. It would involve going back to the server to get the list of formers available. So you would have an AJAX function on the same select that goes back to the server to pull those formers available on the date chosen. The success() method of the AJAX pull would provide the info to re-write the select box, or perhaps even re-make the whole form.
Sorry I can't write all the code, you'll have to fill in the blanks where you can, but this is hopefully enough to help you figure out where to go.

prevent duplicate value using ajax in sugar crm

i have create module using module builder , now i am having a field called as book Name
now if i give same book name 2 time t is accepting .
i don't want to use and plug in for checking duplicate value because i want to learn the customization through code .
so i can call ajax and check in data base weather the same book name is exist in db or not but i don't know how controller works in sugar crm . and how to call ajax in sugar crm .
can any one guide me , your help is much appreciated .
If you really want to accomplish this using ajax then I'd recommend an entryPoint as the way to go. This customization will require a couple of simple things. First you'll write a little bit of javascript to perform the actual ajax call. That ajax call will post to the entryPoint you write. The entryPoint will run the query for you and return a response to you in the edit view. So lets get started by writing the entryPoint first.
First, open the file custom/include/MVC/Controller/entry_point_registry.php. If the folder structure and file do not exist yet, go ahead and create them.
Add the following code to the entry_point_registry.php file:
$entry_point_registry['test'] = array('file' => 'custom/test.php', 'auth' => true);
Some quick explanation about that line:
The index value of test can be changed to whatever you like. Perhaps 'unique_book_value' makes more sense in your case. You'll see how this value is used in a minute.
The file value in the array points to where you're gonna put your actual code. You should also give this a more meaningful name. It does NOT need to match the array key mentioned above.
The 'auth' => true part determines whether or not the browser needs to have an active logged in session with SugarCRM or not. In this case (and almost all) I'd suggest keeping this to true.
Now lets look at the code that will go in custom/test.php (or in your case unique_book_name.php):
/* disclaimer: we are not gonna get all crazy with using PDO and parameterized queries at this point,
but be aware that there is potential for sql injection here. The auth => true will help
mitigate that somewhat, but you're never supposed to trust any input, blah blah blah. */
global $db; // load the global sugarcrm database object for your query
$book_name = urldecode($_REQUEST['book_name']); // we are gonna start with $_REQUEST to make this easier to test, but consider changing to $_POST when confirmed working as expected
$book_id = urldecode($_REQUEST['book_id']); // need to make sure this still works as expected when editing an existing record
// the $db->quote is an alias for mysql_real_escape_string() It still does not protect you completely from sql injection, but is better than not using it...
$sql = "SELECT id FROM book_module_table_name WHERE deleted = 0 AND name = '".$db->quote($book_name)."' AND id <> '".$db->quote($book_id)."'";
$res = $db->query($sql);
if ($db->getRowCount($res) > 0) {
echo 'exists';
}
else {
echo 'unique';
}
A note about using direct database queries: There are api methods you can use to accomplish this. (hint: $bean->retrieve_by_string_fields() - check out this article if you wanna go that route: http://developer.sugarcrm.com/2012/03/23/howto-using-the-bean-instead-of-sql-all-the-time/) However, I find the api to be rather slow and ajax should be as fast as possible. If a client asked me to provide this functionality there's a 99% chance I'd use a direct db query. Might use PDO and parameterized query if I'm feeling fancy that day, but it's your call.
Using the above code you should be able to navigate to https://crm.yourdomain.com/index.php?entryPoint=test and run the code we just wrote.
However at this point all you're gonna get is a white screen. If you modify the url to include the entryPoint part and it loads your home page or does NOT go to a white screen there are 3 potential causes:
You put something different for $entry_point_registry['test']. If so change the url to read index.php?entryPoint=whatever_you_put_as_the_array_key
You have sugar in a folder or something on your domain so instead of crm.yourdomain.com it is located somewhere ugly and stupid like yourdomain.com/sugarcrm/ if this is the case just make sure that your are modifying the url such that the actual domain portion is preserved. Okay I'll spell it out for you... https://yourdomain.com/sugarcrm/index.php?entryPoint=test
This is more rare, but for some reason that I cannot figure out apache sometimes needs to be reloaded when adding a new entrypoint. If you have shell access a quick /etc/init.d/apache2 reload should do the trick. If you don't have shell access you may need to open a ticket with your hosting provider (or get a fricking vps where you have some control!!!, c'mon man!)
Still not working? Did you notice the "s" in https? Try http instead and buy a fricking $9 ssl cert, geez man!
Okay moving on. Let's test out the entryPoint a bit. Add a record to the book module. Let's add the book "War of Art" (no, not Art of War, although you should give that a read too).
Now in the url add this: index.php?entryPoint=test&book_name=Art%20of%20War
Oh gawd that url encoding is hideous right! Don't worry about it.
You should hopefully get an ugly white screen with the text "exists". If you do let's make sure it also works the other way. Add a 2 to the book name in the url and hopefully it will now say "unique".
Quick note: if you're using Sugar you're probably also using mysql which is case insensitive when searching on strings. If you really need case sensitivity check out this SO article:
How can I make SQL case sensitive string comparison on MySQL?
Okay so now we have our entryPoint working and we can move on to the fun part of making everything all ajaxical. There are a couple ways to go about this, but rather than going the most basic route I'm gonna show you what I've found to be the most reliable route.
You probably will need to create the following file: custom/modules/CUSTOM_BOOK_MODULE/views/view.edit.php (I hope by now I don't need to point out changing that path to use your module name...
Assuming this file did not exist and we are starting from scratch here is what it will need to look like:
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
class CUSTOM_BOOK_MODULEViewEdit extends ViewEdit
{
public function display()
{
// make sure it works in the subpanel too
$this->useForSubpanel = true;
// make the name value available in the tpl file
$this->ss->assign('name_value', $this->bean->name);
// load the parsed contents of the tpl into this var
$name_input_code = $this->ss->fetch('custom/modules/CUSTOM_BOOK_MODULE/tpls/unique_book_checker.tpl.js');
// pass the parsed contents down into the editviewdefs
$this->ss->assign('custom_name_code', $name_input_code);
// definitely need to call the parent method
parent::display();
}
}
Things are looking good. Now we gotta write the code in this file: custom/modules/CUSTOM_BOOK_MODULE/tpls/unique_book_checker.tpl.js
First a couple of assumptions:
We're going to expect that this is Sugar 6.5+ and jquery is already available. If you're on an earlier version you'll need to manually include jquery.
We're going to put the event listener on the name field. If the book name value that you want to check is actually a different field name then simply adjust that in the javascript below.
Here is the code for custom/modules/CUSTOM_BOOK_MODULE/unique_book_checker.tpl.js:
<input type="text" name="name" id="name" maxlength="255" value="{$name_value}" />
<span id="book_unique_result"></span>
{literal}
<script type="text/javascript">
$(document).ready(function() {
$('#name').blur(function(){
$('#book_unique_result').html('<strong> checking name...</strong>');
$.post('index.php?entryPoint=test', {book_name: $('#name').val(), book_id: $('[name="record"]').val()}, function(data){
if (data == 'exists') {
removeFromValidate('EditView', 'name');
addToValidate('EditView', 'name', 'float', true, 'Book Name Must be Unique.');
$('#book_unique_result').html('<strong style="color:red;"> ✗</strong>');
}
else if (data == 'unique') {
removeFromValidate('EditView', 'name');
addToValidate('EditView', 'name', '', true, 'Name Required');
$('#book_unique_result').html('<strong style="color:green;"> ✓</strong>');
}
else {
// uh oh! maybe you have php display errors on?
}
});
});
});
</script>
{/literal}
Another Note: When the code detects that the name already exists we get a little hacky and use Sugar's built in validation stuff to prevent the record from saving. Basically, we are saying that if the name already exists then the name value MUST be a float. I figured this is pretty unlikely and will do the trick. However if you have a book named 3.14 or something like that and you try to create a duplicate this code will NOT prevent the save. It will tell you that a duplicate was found, but it will not prevent the save.
Phew! Okay last two steps and they are easy.
First, open the file: custom/modules/CUSTOM_BOOK_MODULE/metadata/editviewdefs.php.
Next, find the section that provides the metadata for the name field and add this customCode attribute so that it looks like this:
array (
'name' => 'name',
'customCode' => '{$custom_name_code}',
),
Finally, you'll need to do a quick repair and rebuild for the metadata changes to take effect. Go to Admin > Repair > Quick Repair & Rebuild.
Boom! You should be good to go!

django update page when database field updates?

I have a results page and I am trying to work out how to auto update the page when an external database field is updated. I have seen quite a few examples but they seem to relate to PHP. I have a test that calls various APIs that can take up to an hour to complete. Once the test has completed, it will enter a success or failed message in a database field.
I already have my results page being rendered by django using template tags. I have a table and I have the field I would like to update. There are multiple fields that need update which correspond to each API test.
I have seen this site.. is this the kind of stuff to use? http://www.dajaxproject.com/ Is this an easy task to do? Does anyone have any ideas on how to do this?
Sorry but I don't know where to start on this one.
Cheers - Oli
I decided not to be so bold and just use the old classic page update for this purpose using javascript..
window.onload = setupRefresh;
function setupRefresh() {
setTimeout("refreshPage();", 30000); // milliseconds
}
function refreshPage() {
window.location = location.href;
}
Still open for options however I'm rather inexperienced in django and maybe this was too much to bite off too quickly..

cakephp 2.1 view associated data across all add.ctp, edit.ctp, view.ctp

I have an "examinations" table, its consultation_id relates to "consulsations" table, which in turn its consulation_id relates to the "patients" table.
Now, when I am in the add.ctp, edit.ctp or view.ctp of the "Examinations" Views I need to pull the "patients" details in so that some patient info can appear as to who the form pertains to as patient.
I have tried joins. Not to say they dont work. I am new to cakephp and I really need help as to how it will appear within the controller and how the view.ctp will display it.
I thought of elements but they are just .ctp files right?
Please if anyone can help regarding this it would be so appreciated. I've been trying to do this now for a week and I know there is something simple I am dont doing or thinking rights about.
So you just want to pull in related data? Pretty simple.
In your ExaminationsController methods.
$patients = $this->Examination->Consultation->Patient->find('all',
array('conditions'=>array('consultation_id'=>$id,'examination_id'=>$e_id)));
Something similar to this, not quite sure on which id you need to pass, as it will depend on how your models are linked up. http://book.cakephp.org/2.0/en/models/retrieving-your-data.html
However, if your models are linked up properly, you should get this data anyway. If not set your models recursion to be higher.
$this->Model->recursive = 2;

Forcing JQuery Datatable to load data via AJAX upon selection of a date range

I have the wonderful jquery data tables currently loading data using ajax.
The code is pretty much the same as the example I took it from which can be found at: http://www.datatables.net/release-datatables/examples/server_side/pipeline.html
I found this the best example because it incoporates pagination, sorting and also the search box into the ajax requests. The search box allows you to type in key words and this triggers the ajax function which includes the search value as a $_GET var to the server script.
This is a small preview of my table with table tools etc. loaded.
http://img828.imageshack.us/img828/9778/previewxjh.png
As you can see the main focus here is the filament groups date range plugin which I have added. I have finished with this now, and have a fail safe for the duplicate event firing problem etc. its ready to go and just needs including in the ajax pipeline - which is where I have been stuck for the last day or so.
fnDataTablesPipeline appears to be just an interim and doesnt reference the search box at all, so I can't figure out how the search box is working, and I am unsure if this is the right place to go including my date range value (everything I have tried just leads me to a dead end)
I want to use my onChange event for the date range filter, and apply it exactly the same way that the search box works. When the value is changed, simply pass it as a get variable so that my php script can deal with it there. I have concerns regarding the paging, and I will probably need to just reset back to page one after the date is changed (not sure how I am going to deal with this just yet, but thats the next step)
I need help telling datatables to refresh from the ajax source, and include the date range as a get parameter to the server side script (like when the search box value changes)
- sounds straight forward, but this is where I am breaking down and not making good use of my time due to the lack of understanding.
Is there anyone that has implemented similar that can help me?
The biggest problem right now is how to force the refresh from my date range onChange event, and of course include the single string value which contains my dates (which I know how to cover server side)
Many Thanks,
Chris
EDIT: I actually managed to get this working before I finished for the day. I'll post my code when I get back in the office tomorrow, it was actually surprisingly easy - I was tackling it completely wrong.
After changing date..
oTable.fnClearTable(0);
oTable.fnDraw();
Include var in pipeline
function fnDataTablesPipeline ( sSource, aoData, fnCallback, dateRange ) {
aoData.push( { "name": "dateRange", "value": $('#dateRangePicker').val(), } );
...
Obtain var in php script
$_GET['dateRange']

Resources