How can I do infinite scrolling in ionic 1 and angular js 1 with dynamic data (Http request)from database ?
HTML :
<ion-view view-title="Playlists">
<ion-content>
<ion-list>
<ion-item class="item-avatar" ng-repeat="item in items">
<h2>{{item.name}} -{{item.id}}</h2>
<p>{{item.iso_code_2}} {{item.iso_code_3}}</p>
</ion-item>
</ion-list>
<div ng-if="hasData">
<ion-infinite-scroll on-infinite="loadMore()" distance="5%">
</ion-infinite-scroll>
</div>
</ion-content>
</ion-view>
Controller.js
This is my angularjs controller. Use a factory named 'CountryService' which is doing http call to get server data. In formdata = {limit:serviceconfig.showlimit,page:page}; I sent limit =10 where I set in config.js service,and set page =1 for the first time.
For the first time GetDefault is called after scrolling GetLoadMore will be called with page =2 and limit=10 with next 10 new data.
angular.module('starter.usercontroller', [])
.controller('UserCtrl', function($scope, CountryService, $ionicModal,
$timeout, $http, serviceconfig, $ionicPopup,$state, ionicDatePicker, $filter) {
$scope.hasData=1; // If data found
$scope.items = [];
CountryService.GetDefault().then(function(items){
$scope.items = items;
});
$scope.loadMore = function() {
CountryService.GetLoadMore().then(function(items){
$scope.items = $scope.items.concat(items);
if(items.length>0)
{
$scope.$broadcast('scroll.infiniteScrollComplete'); // If has data then load more
}
else
{
$scope.hasData=0; // If no more data to load
}
});
};
})
.factory('CountryService',
['$http','serviceconfig',function($http,serviceconfig){
var items = [];
var page =1;
var formdata = {limit:serviceconfig.showlimit,page:page};
return {
GetDefault: function(){
formdata = {limit:serviceconfig.showlimit,page:page};
return $http.post(serviceconfig.serviceUrl+ "all-countries",formdata).then(function(response){
if(response.data.status==1)
{
items = response.data.countries;
}
else
{
items =[];
}
return items;
});
},
GetLoadMore: function(){
formdata = {limit:serviceconfig.showlimit,page:page};
return $http.post(serviceconfig.serviceUrl+ "all-countries",formdata).then(function(response){
page = page+1;
if(response.data.status==1)
{
items = response.data.countries;
}
else
{
items =[];
}
return items;
});
}
}
}]);
Config.js For configuration
In this config.js I set the server url and limit, how many data I want to fetch from server each scroll. 'configService' service I inject in my js controller.
angular.module('starter.configService', [])
.service('serviceconfig',function(){
this.serviceUrl='http://192.168.1.116/ionicserver/service/';
this.showlimit=10;
})
PHP SERVER SITE CODE:
I am using php laravel 5.1. So this is my php controller function for getting county list by below function
public function postAllCountries() // Countries
{
$data = Request::all();
$limit= $data['limit'];
$page = $data['page'];
$offset = ($page - 1) * $limit;
$countries = Country::where('id','>',0)->take($limit)->skip($offset);
$countries = $countries->get()->toArray();
if(!empty($countries))
{
echo json_encode(array('status'=>1,'msg'=>'Successfully Registered','countries'=>$countries));
}
else
{
echo json_encode(array('status'=>0,'msg'=>'No data found'));
}
exit;
}
Related
I am submitting data to a controller function via AJAX, doing what I need to do with the data, and trying to echo it back out to the ajax function.
The issue I am having, is the controller is dumping out the error message and trying to redirect me to the actual function. Obviously the function doesn't have a view, which results in a blank white screen with the response echoed out in the top left corner.
Here is the ajax:
$('#submit_new_split_promo').on('click',function(e){
e.preventDefault();
var id = $(this).data('id');
$('#d_overlay').show();
form = {};
$.each($('#promo-mail-split-add-'+id).serializeArray(),function(k,v){
form[this.name] = this.value;
});
$.ajax({
url:$('#promo-mail-split-add-'+id).attr('action'),
type:"POST",
dataType: "json",
data: form
}).done(function(result){
var res = JSON.parse(result);
if (res == 'Duplicate') {
$('#ms-promo').css('border','3px solid red');
$('#ms-promo').effect('shake');
$('#dynamodal-unique-title').text('That code has been used. Please enter a new Promo Code.');
$('#dynamodal-unique-title').text('That code has been used. Please enter a new Promo Code.').css('color','red').delay(2000).queue(function(next){
$('#dynamodal-unique-title').text('Create Mail Split Promo');
next();
});
return false;
}
$('#mail_split_promo_'+id).modal('toggle');
if (res == false) {
alert('Mail Split Promo did not save. Please try again.');
} else {
$('#add-promo-to-split-'+id).prop('disabled',true);
$('#promo-view-abled-'+id).hide();
$('#promo-view-disabled-'+id).show();
$('#promo-view-disabled-'+id).prop('disabled',false);
}
}).fail(function(){
}).always(function(){
$('#d_overlay').hide();
});
});
Here is the Controllers code
public function addpromo() {
$this->Authorization->skipAuthorization();
$this->request->allowMethod(['get','post']);
$this->autoRender = false;
$data = $this->request->getData();
$mail_split_id = $data['mail_split_id'];
$code = $data['code'];
$result = false;
$doesExist = $this->Promos->findByCode($code)->toArray();
if ($doesExist) {
$result = 'Duplicate';
}
if ($result !== 'Duplicate') {
$MailSplits = $this->getTableLocator()->get('MailSplits');
$mailSplit = $MailSplits->get($mail_split_id);
$entity = $this->Promos->newEmptyEntity();
foreach ($data as $key => $val) {
$entity->$key = $val;
}
$entity->record_count = $mailSplit->record_count;
$result = $this->Promos->save($entity);
if ($this->get_property($result,'id')) {
$promo_id = $result->id;
$MailSplits = $this->loadModel('MailSplits');
$mentity = $MailSplits->get($mail_split_id);
$mentity->promo_id = $promo_id;
$updated = $MailSplits->save($mentity);
if ($this->get_property($updated,'id')) {
$result = true;
} else {
$result = false;
}
$output = [];
exec(EXEC_PATH.'AddPromoToRecordSplits '.$promo_id,$output);
} else {
$result = false;
}
}
ob_flush();
echo json_encode($result);
exit(0);
}
The URL it is trying to redirect me to is: /promos/addpromo when I really just need to stay on the same page, which would be /mail-jobs/view
Response dumped to browser
A couple of things to note:
I have tried adding the function to the controllers policy, and actually authorizing an initialized entity. This has no effect and does not change the issue I am facing.
Something that is more frustrating, I have essentially the same code (ajax structure and controller structure) for other forms on the page, and they work just fine. The only difference seems to be any form that utilizes ajax that is on the page on render, works just fine. The ajax functions I am having an issue with, all seem to be from the forms rendered in Modals, which are different elements. Every form in a modal / element, gives me this issue and that's really the only pattern I have noticed.
Any help is greatly appreciated, I know it's an odd and vague issue.
Thank you!
I have some difficulties with my ajax pagination linked to a filter. Here's how it should work. The user can access via a specific page to a form. When clicking the submit button, a raw sql request is made in JS and a POST ajax request is achieved to get the results at the bottom of the page with a pagination menu. This part works. But I have some issues with the pagination menu because the links don't work. For example, by clicking the "page 2" link, nothing happens.
Here are the different parts of my code:
Routes
Route::get('articles/filter', 'ArticleController#filterx');
Route::post('articles/request/ajax/articles/filter', 'ArticleController#filtery');
Route::get('articles/request/ajax/articles/filter', 'ArticleController#filtery');
Controller
ArticleController
public function filterx() { // get filter page
return view('filter');
}
public function filtery(Request $request) { // filter ajax function
$articles = Article::paginate(2);
if($request->ajax()) {
// partial view returned in html
return $html = view('filterResults', compact('articles'));
}
}
Views
filter.blade.php
#extends('layouts/app')
#section('title')
Title
#endsection
#section('content')
<div class="container">
<!-- filter -->
<h2>Filter</h2>
<div class="content-card content">
<form method="POST" action="">
<!-- form code... -->
</form>
</div>
<div id="filter-results">
</div>
</div>
#endsection
filterResults.blade.php
#foreach($articles as $article)
<p>{{ $article->name }}</p>
#endforeach
{{ $articles->links() }}
Javascript
$("#submit-button").click(function(e) {
e.preventDefault();
// ajax request (raw mysql request)
var requestQuery = ...; // (quite long) raw request
console.log(requestQuery); // console verification of request
$.ajax({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
url: '../articles/request/ajax/articles/filter',
type: 'POST',
data: {
request: requestQuery
},
success: function(html) {
$("#filter-results").empty().html(html);
}
});
});
$(window).on('hashchange', function() {
// if hash in url
if (window.location.hash) {
// page contains hash value
var page = window.location.hash.replace('#', '');
if (page == Number.NaN || page <= 0) {
return false;
}
// if ok ->getData returned
else {
getData(page);
}
}
});
$(document).on('click', '.pagination a', function(e) {
e.preventDefault();
$('.pagination li').removeClass('active');
$(this).parent('li').addClass('active');
var url = $(this).attr('href');
var page = $(this).attr('href').split('page=')[1];
getData(page,url);
});
function getData(page,url) {
$.ajax(
{
url: url,
type: 'get',
datatype: 'html',
done: function(data) {
console.log('ok');
$('#filter-results').empty().html(data);
location.hash = page;
},
fail: function(jqXHR, ajaxOptions, thrownError) {
console.log('No response from server');
}
});
}
I don't understand why it is not working, I thing I misunderstood something.
Thanks and have a good day
Laravel uses the page value from the request, or query string, by convention. If you choose not to use that, you can set your own. If following convention, you'd need to append the query string page=# to your url in the ajax request.
The fourth argument of the Builder::paginate is the page number:
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$perPage = $perPage ?: $this->model->getPerPage();
$results = ($total = $this->toBase()->getCountForPagination())
? $this->forPage($page, $perPage)->get($columns)
: $this->model->newCollection();
return $this->paginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}
You could also define your own page resolver. The default is set in PaginationServiceProvider:
Paginator::currentPageResolver(function ($pageName = 'page') {
$page = $this->app['request']->input($pageName);
if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int) $page >= 1) {
return (int) $page;
}
return 1;
});
Route::get('articles/filter/{page}', 'ArticleController#filter');
public function filter(Request $request, int $page) {
$articles = Article::paginate($page);
}
it's all
Here is my AngularJS code for building the pagination with angular bootstrap pagination:
$scope.employees = [],
$scope.currentPage = 0,
$scope.numPerPage = 2,
$scope.totalItems = '',
$scope.maxSize = 2;
$scope.getEmployee = function (offset) {
$http.get('/employee/'+offset).then(function (response) {
$scope.employees = response.data.data;
$scope.totalItems= response.data.totalRows;
console.log($scope.totalItems);
});
};
$scope.getEmployee(0);
$scope.getPage = function () {
$scope.getEmployee($scope.currentPage === 1 ? 0 : $scope.currentPage);
};
Trying to list 2 employees per page (Now i have 6 rows in mysql query)
Laravel controller
public function getTotalEmployees($offset)
{
$result = Company::limit(2)->offset($offset)->get();
return response()->json(array('data'=>$result,'totalRows'=>Company::count()));
}
query will give correct output but the paginationbar is not properly displayed.
HTML
<ul>
<li ng-repeat="emp in employees">{{emp.name}}</li>
</ul>
<pagination
ng-model="currentPage"
total-items="20"
max-size="maxSize"
boundary-links="true"
ng-change="getPage()">
</pagination>
I think its the problem with totalItems value but i can't fixed it here is screenshot of the pagination bar
I can't select the next and previous buttons its disabled
Somethink like this. I'm not that familiar with laravel but it should work with mini modifications for you. I added an other controller action in laravel which return you the total count of your items. This API endpoint is called on this.$onInit which is a methods available since AngularJS 1.5. It will be called when the controller is initialized. Here is a simple fiddle demo with an pagination example.
AngularJS controller
$scope.employees = [],
$scope.currentPage = 0,
$scope.numPerPage = 2,
$scope.totalItems = 0,
$scope.maxSize = 2;
this.$onInit = function () {
$scope.getEmployee();
$http.get('/employee/getTotalCount').then(function (response) {
$scope.totalItems = response.data.count;
});
};
$scope.getEmployee = function () {
$http.get('/employee/getItems/'+ ($scope.currentPage * $scope.numPerPage) +'/' + $scope.numPerPage).then(function (response) {
$scope.employees = response.data.data;
});
};
$scope.getPage = function () {
$scope.getEmployee();
};
Laravel controller
public function getTotalCount()
{
$companies = Company::all();
return response()->json('count' => $companies->count());
}
public function getItems($offset, $limit)
{
$result = Company::limit($limit)->offset($offset)->get();
return response()->json(array('data'=>$result));
}
I am trying to populate a select list with data from my db (php & mysql). I am working with AngularJs and Angular Material. So for i am not able to show the data from the db in the list
db situation:
tblProjectType -> name of table
2 rows:
id_ProjectType
project_type
Any help or pointers would be great.
This is my html code:
<form ng-controller="AppCtrl">
<div layout="row">
<md-select-label>Project type</md-select-label>
<md-select ng-model="project_type" name="project_type" placeholder="Choose a project type" id="containerProjectType">
<md-option ng-repeat="projecttype in projecttypes" value="{{projecttype.id_ProjectType}}">{{projecttype.project_type}}</md-option>
</md-select>
</div>
</form>
The code of my app.js is:
var app = angular.module("DragDrop", ['ngMaterial']);
app.controller('AppCtrl', function($scope, $mdDialog, $http) {
$scope.projectTypeInfo = [];
var getProjectTypeFunction = function(succesFn, errorFn)
{
$http.get('db.php?action=get_ProjectType_info')// call to the server
.succesFn(function(data){
succesFn(data); //call the function passed into getProjectTypeFunction with the data from the server
console.log('Retrieved data from server');
})
.error(errorFn || function() {
console.log("Error in retrieving data from server");
})
}
this.reloadProjectTypeList = function()
{
getProjectTypeFunction(
/* success function */
function(data) {
//debugger;
$scope.projectTypeInfo = data;
//digest recycle
//if (!$scope.$$phase) { $scope.$apply(); }
},
/* error function */
function()
{
alert("Server load failed");
})
};
My php code is:
<?php
include('config.php');
//echo ('test' . $_GET['action']);
switch($_GET['action']) {
case 'get_ProjectType_info' :
get_ProjectType_info();
break;
}
/** Function to data from tblProjectType **/
function get_ProjectType_info(){
$qry = mysql_query('SELECT * from tblProjectType');
echo("test");
//echo(qry);
$data = array();
while($rows = mysql_fetch_array($qry))
{
$data[] = array(
"id_ProjectType" => $rows['id_ProjectType'],
"project_type" => $rows['project_type']
);
}
print_r(json_encode($data));
return json_encode($data);
}
?>
So for starters lets clean up your JS. We can reduce what you have to this:
var app = angular.module("DragDrop", ['ngMaterial']);
app.controller('AppCtrl', function($scope, $mdDialog, $http)
{
$scope.projectTypeInfo = [];
$scope.getProjectTypeFunction = function()
{
$http.get('db.php?action=get_ProjectType_info')
.success(function(data, status, headers, config)
{
$scope.projectTypeInfo = data;
console.log('Retrieved data from server');
console.log(data);
})
.error(function(data, status, headers, config)
{
console.log("Error in retrieving data from server");
console.log(data,status);
});
};
$scope.getProjectTypeFunction(); //-- call the function that invokes $http.get()
};
In PHP your function needs to echo the data via echo json_encode($data);, not return it (as stated by #Avalanche).
Now, your console should output something, but you need to remove console.log("test"); from your PHP as that will surely cause an error.
edit
Currently your repeat states:
<md-option ng-repeat="projecttype in projecttypes" value="{{projecttype.id_ProjectType}}">{{projecttype.project_type}}</md-option>
We have stored your data in $scope.projectTypeInfo therefore it needs to be modified to:
<md-option ng-repeat="projecttype in projectTypeInfo" ng-value="projecttype.id_ProjectType">{{projecttype.project_type}}</md-option>
I'm using this function to try and send my objects coordinates and id to my php script. I'm not sure how to setup how to get the card_id and it's top and left coordinates into the post so I can retrieve them in my php script as one array. I have the all the values alerting properly but how do I pass them make sure I'm getting the proper ones on the other end and that the coordinates go with the card_id?
document.getElementById('rasterize-scoutlog2').onclick = function() {
if (!fabric.Canvas.supports('toDataURL')) {
alert('This browser doesn\'t provide means to serialize canvas to an image');
}
else {
canvas.deactivateAllWithDispatch().renderAll();
//window.open(canvas.toDataURL('png'));
//var strDataURI = (canvas.toDataURL('png'));
//strDataURI = strDataURI.substr(22, strDataURI.length);
var objsInCanvas = canvas.getObjects();
objsInCanvas.forEach(function(object) {
var stickycard_ids = [object.card_id];
var stickycard_top = [object.top];
var stickycard_left = [object.left];
if(object.card_id != null){
stickycard_ids.forEach(function(stickycard_idarr) {
alert(stickycard_idarr+stickycard_top+stickycard_left);
});
}
});
var scoutlogname = $('#scoutmapselectcard').val();
$.post("maps/savescout_log.php",
{
//str: strDataURI,
// queryStr: queryStr,
scoutlogname: scoutlogname,
//**** stickycard_idarr: stickycard_idarr
},
function(data){
if(data == "OK"){
$("#msg").html("Scout Log saved to account!").css({'color':"green",'font-weight':"bold"});
}
if(data=="EMPTY"){
$("#msg").html("Please Enter a name for your Scout Log!").css({color:"red"});
}
if(data=="WRONGCH"){
$("#msg").html("Only A_Z,a-z,0-9-_ allowed in Scout Log name!").css({color:"red"});
}
if(data=="EXIST"){
$("#msg").html("Scout Log name all ready exists!<br> Delete the existing one before saving.").css({color:"red"});
}
if(data=="ERROR"){
$("#msg").html("Scout Log not saved!").css({color:"red"});
}
window.setTimeout(function() {
$('#msg').empty();
}, 5000);
});
}
};
I got the objects and their details all going to arrays. I used the .push method to populate the arrays with the objects values in the foreach loop. Now on to the php end to insert them into the mysql database table.
document.getElementById('rasterize-scoutlog').onclick = function() {
if (!fabric.Canvas.supports('toDataURL')) {
alert('This browser doesn\'t provide means to serialize canvas to an image');
}else {
canvas.deactivateAllWithDispatch().renderAll();
//window.open(canvas.toDataURL('png'));
//var strDataURI = (canvas.toDataURL('png'));
//strDataURI = strDataURI.substr(22, strDataURI.length);
var objsInCanvas = canvas.getObjects();
var stickycard_ids = [];
var stickycard_top = [];
var stickycard_left = [];
var stickycard_type = [];
objsInCanvas.forEach(function(object) {
if(object.card_id != null){
stickycard_ids.push(object.card_id);
stickycard_top.push(object.top);
stickycard_left.push(object.left);
stickycard_type.push(object.cardtype);
}
});
var scoutmapname = $('#scoutmapselectcard').val()
var scoutlogname = $('#scoutlogname').val();
$.post("maps/savescout_log.php",
{
//str: strDataURI,
//queryStr: queryStr,
scoutlogname: scoutlogname,
scoutmapname: scoutmapname,
stickycard_ids: stickycard_ids,
stickycard_top: stickycard_top,
stickycard_left: stickycard_left,
stickycard_type:stickycard_type
},
function(data){
if(data == "OK"){
$("#msg").html("Scout Log saved to account!").css({'color':"green",'font-weight':"bold"});
}
if(data=="EMPTY"){
$("#msg").html("Please Enter a name for your Scout Log!").css({color:"red"});
}
if(data=="WRONGCH"){
$("#msg").html("Only A_Z,a-z,0-9-_ allowed in Scout Log name!").css({color:"red"});
}
if(data=="EXIST"){
$("#msg").html("Scout Log name all ready exists!<br> Delete the existing one before saving or enter a new name.").css({color:"red"});
}
if(data=="ERROR"){
$("#msg").html("Scout Log not saved!").css({color:"red"});
}
window.setTimeout(function() {
$('#msg').empty();}, 5000);
});
}
};
Here's the php that will insert those mutiple arrays into into mysql using PDO. I'm using the stickycard_ids as the indexing value then posting that and the other assiociated array values to a new row every time the stickycard_ids value changes.
for ($i=0; $i < count($_POST['stickycard_ids']); $i++ ) {
$card_id = $_POST['stickycard_ids'][$i];
$cardtype = $_POST['stickycard_type'][$i];
$top_y = $_POST['stickycard_top'][$i];
$left_x = $_POST['stickycard_left'][$i];
$sql ="INSERT INTO tablename (scoutmapname,scoutlogname,card_id,left_x,top_y,cardtype)
VALUES (:scoutlogname,:card_id,:left_x,:top_y,:cardtype)";
$q = $pdo->prepare($sql);
$q->execute(array(':scoutmapname'=>$scoutmapname,':scoutlogname'=>$scoutlogname,':card_id'=>$card_id,':left_x'=>$left_x,':top_y'=>$top_y,':cardtype'=>$cardtype));
}