Factory with database request


#1

Hey guys,

i try to do an database-request in a factory, but something went wrong.
here the code of the controller:

.controller('TestCtrl', function($scope, pizzaService) {
  $scope.pizzas = pizzaService.all();
})

And here the code of the service:

.factory('pizzaService', function($http) {
  // Might use a resource here that returns a JSON array

  // Some fake testing data
  $http.get("http://localhost/soundso/www/php/load_Pizzas.php").success(function(data){
  var pizzas = data;
  });

  return {
    all: function() {
      return pizzas;
    }
  };
});

This error occurs:

Error: Can't find variable: pizzas

When i load just the php-file, this is the output:

{"pizzas":[{"id":1,"name":"Pizza Vegetaria","price":"5.00"},{"id":2,"name":"Salami","price":"5.50"},{"id":3,"name":"Thunfisch","price":"6.00"}]}

What is the failure?


#2

You have a scope problem of the variable.

Your init the var inside the success function of your $http. this means you only have access to this variable inside this function.

if you do something like this it should work:

.factory('pizzaService', function($http) {
  // Might use a resource here that returns a JSON array
 var pizzas = {};
  // Some fake testing data
  $http.get("http://localhost/soundso/www/php/load_Pizzas.php").success(function(data){
  this.pizzas = data;
  });

  return {
    all: function() {
      return this.pizzas;
    }
  };
});

im not sure if this is needed but it should work.


#3

Yes, it works fine! Thanks!

The data is loaded, but i still see no output at the site.

Here the html-code:

<ion-view view-title="Pizzas">
  <ion-content>
  	<label class="item item-input">
  		<input type="text" ng-model="search" placeholder="Suchtext">
	</label>
    <p ng-show="search">Du suchst gerade nach: {{search}}</p>
    <ion-search placeholder="ion Suche" filter="search"></ion-search>
    <ion-list>

      <ion-item class="item-divider">Pizzas</ion-item>

      <ion-item ng-repeat="pizza in pizzas | filter:search" class="item-remove-animate item-icon-right">
        <h2>{{pizza.name}}</h2>
        <p>Preis: {{pizza.price}} Euro</p>
        <i class="icon ion-chevron-right icon-accessory"></i>
        <ion-option-button class="button-assertive" >
          Löschen
        </ion-option-button>
      </ion-item>

    </ion-list>
  </ion-content>
</ion-view>

Is there also an “this.” neccessary?


#4

nope this is not required, coze you bind to a $scope variable.

but what i saw when your data is returned like this:

{"pizzas":[
       {"id":1,"name":"Pizza Vegetaria","price":"5.00"},
       {"id":2,"name":"Salami","price":"5.50"},
       {"id":3,"name":"Thunfisch","price":"6.00"}
 ]}

in your $scope.pizzas there is a object pizzas and not the array of the actual pizzas.

what you have to do is this: ng-repeat=“pizza in pizzas.pizzas | filter:search”

then it should work!


#5

And what do i have to change, to get an array from the php-file?

here the code:

<?php
error_reporting(-1);
include_once 'db_connect.php';
include_once 'functions.php';
sec_session_start();

$suche = 1;
if($stmt = $mysqli->prepare(
          "SELECT 
            id,
            name,
            price
           FROM 
            pizzatab
           WHERE
            price > ?
            ")) {
  $stmt->bind_param("i",  $suche);
  $stmt->execute();
  $stmt->bind_result($id, $name, $price);

  while($stmt->fetch())   {
  $pizzaarray[] = array(
      "id"                  => $id, 
      "name"                => $name, 
      "price"               => $price,
      );
                          }

  $stmt->close();
}
echo json_encode(array('pizzas' => $pizzaarray))
?>

I have tried array_values, but this doesn’t work.


#6

does the current php file return this:

 {"pizzas":[{"id":1,"name":"Pizza Vegetaria","price":"5.00"},{"id":2,"name":"Salami","price":"5.50"},{"id":3,"name":"Thunfisch","price":"6.00"}]} 

if so your fine. everything should work


#7
.factory('pizzaService', function($http,$q) {

    var self = this;

    self.all = function(){

    var deferred = $q.defer();

    $http.get("http://localhost/soundso/www/php/load_Pizzas.php").success(function(data){
        deferred.resolve(data) ;
    }).error(function(error){
        deferred.reject(error)
    });

    return deferred.promise;

    };

    return self;

});

I’d use the deferred method then upon resolving the data that data is then returned rather than nothing.


#8

It actually doens’t work with:

But i want, that it works with:
ng-repeat=“pizza in pizzas | filter:search”

@webslinger
Could you short explain me, what the deferred method does? after i read docs, i think it is just for asynchronous request and shows the data, when it is loaded, right?

Here the PHP-output:

[Log] Object (services.js, line 57)
pizzas: Array[3]
0: Object
id: 1
name: "Pizza Vegetaria"
price: "5.00"
__proto__: Object
1: Object
id: 2
name: "Salami"
price: "5.50"
__proto__: Object
2: Object
id: 3
name: "Thunfisch"
price: "6.00"
__proto__: Object
length: 3
__proto__: Array[0]
__proto__: Object

#9

so your output is on this line:
$http.get(“http://localhost/soundso/www/php/load_Pizzas.php”).success(function(data){
this.pizzas = data;
});

right?

if you want to use: ng-repeat="pizza in pizzas | filter:search"
change your factory to:

all: function() {
    return this.pizzas.pizzas;
  }

or change your php to only return the array of pizzas: if im right i would look like this:

echo json_encode($pizzaarray)

#10

Mmmh, both is not working :confused:

Yes, it is so.


#11

I think if you try this

this.pizzas = data.pizzas

this should return you pizza objects


#12

also not working. just errors.


#13

can u past your current service and controller and output in console of you array


#14

Here the code of the controller:

controller.js

angular.module('starter.controllers', [])

.controller('DashCtrl', function($scope) {})

.controller('TestCtrl', function($scope, pizzaService) {
  $scope.pizzas = pizzaService.all();
})

.controller('ChatsCtrl', function($scope, Chats) {
  $scope.chats = Chats.all();
  $scope.remove = function(chat) {
    Chats.remove(chat);
  }
})

.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
  $scope.chat = Chats.get($stateParams.chatId);
})


.controller('AccountCtrl', function($scope) {
  $scope.settings = {
    enableFriends: true
  };

});

service.js

angular.module('starter.services', [])
.factory('pizzaService', function($http) {
var pizzas = {};
  $http.get("http://localhost/whatever/www/php/load_Pizzas.php").success(function(data){
  this.pizzas = data;
  console.log('success - pizzas loaded');
  console.log(this.pizzas);
  });

  return {
    all: function() {
      return this.pizzas;
    }
  };
});

load_Pizzas.php

<?php
error_reporting(-1);
include_once 'db_connect.php';
include_once 'functions.php';
sec_session_start();

$suche = 1;
if($stmt = $mysqli->prepare(
          "SELECT 
            id,
            name,
            price
           FROM 
            pizzatab
           WHERE
            price > ?
            ")) {
  $stmt->bind_param("i",  $suche);
  $stmt->execute();
  $stmt->bind_result($id, $name, $price);

  while($stmt->fetch())   {
  $pizzaarray[] = array(
      "id"                  => $id, 
      "name"                => $name, 
      "price"               => $price,
      );
                          }

  $stmt->close();
}
echo json_encode($pizzaarray)
?>

load_PIzzas Output

[{"id":1,"name":"Pizza Vegetaria","price":"5.00"},{"id":2,"name":"Salami","price":"5.50"},{"id":3,"name":"Thunfisch","price":"6.00"}]

#15

Pizzas

  <ion-item ng-repeat="pizza in pizzas **| filter:search" class="item-remove-animate item-icon-right"**>
    <h2>{{pizza.name}}</h2>
    <p>Preis: {{pizza.price}} Euro</p>
    <i class="icon ion-chevron-right icon-accessory"></i>
    <ion-option-button class="button-assertive" >
      Löschen
    </ion-option-button>
  </ion-item>

Remove the filter you put on the ng-repeat and try again ?


#16

as somebody writes in stackoverflow the problem is the payload, so i don’t wait for the output.


#17

in that cause put your service request in a promise and let it return a promise

and then in your controller you can do

pizzaService.all()
.then (function(results) {
$scope.pizzas = results
alert('Success: ’ + results);
}, function(results) {
alert('Failed: ’ + results);
});


#18

Okay. And how do i filter this values?

Here is the example of the chats-tab from the standard-ionic-app:

angular.module('starter.services', [])
 
.factory('Chats', function() {
  // Might use a resource here that returns a JSON array
 
  // Some fake testing data
  var chats = [{
    id: 0,
    name: 'Ben Sparrow',
    lastText: 'You on your way?',
    face: 'https://pbs.twimg.com/profile_images/514549811765211136/9SgAuHeY.png'
  }, {
    id: 1,
    name: 'Max Lynx',
    lastText: 'Hey, it\'s me',
    face: 'https://avatars3.githubusercontent.com/u/11214?v=3&s=460'
  },{
    id: 2,
    name: 'Adam Bradleyson',
    lastText: 'I should buy a boat',
    face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg'
  }, {
    id: 3,
    name: 'Perry Governor',
    lastText: 'Look at my mukluks!',
    face: 'https://pbs.twimg.com/profile_images/598205061232103424/3j5HUXMY.png'
  }, {
    id: 4,
    name: 'Mike Harrington',
    lastText: 'This is wicked good ice cream.',
    face: 'https://pbs.twimg.com/profile_images/578237281384841216/R3ae1n61.png'
  }];
 
  return {
    all: function() {
      return chats;
    },
    remove: function(chat) {
      chats.splice(chats.indexOf(chat), 1);
    },
    get: function(chatId) {
      for (var i = 0; i < chats.length; i++) {
        if (chats[i].id === parseInt(chatId)) {
          return chats[i];
        }
      }
      return null;
    }
  };
})

#19

if you want filter by search for example

Search by color:

if you want to hard code it