Ankündigung

Einklappen
Keine Ankündigung bisher.

[AngularJS] Frage zu $resource

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [AngularJS] Frage zu $resource

    Ich baue hier gerade eine kleine App, die als REST Endpoint ein .json File verwendet und je einen View für die Liste aller Einträge, sowie die Details des ausgewählten Eintrages anzeigen soll. Dabei scheitere ich aber am Detail-Controller. Ich habe das Nachfolgende bei Plunker nachgestellt.

    http://plnkr.co/edit/kERtF6ETfl0WcsvoniAp?p=preview

    Code:
    //JSON Object
    [
      {"user_id": 1, "user_firstname": "Frank", "user_lastname": "Meier"},
      {"user_id": 2, "user_firstname": "Franziska", "user_lastname": "Schulze"}
    ]
    
    //Router
    app.config(['$routeProvider', function ($routeProvider) {
      $routeProvider.
        when('/', {
          templateUrl: 'users.html',
          controller: 'ListCtrl'
        }).
        when('/users/:user_id', {
          templateUrl: 'details.html',
          controller: 'DetailCtrl'
      });
    }]);
    
    //Controller
    app.controller('ListCtrl', function($scope, Users) {
      $scope.users = Users.query();
    });
    app.controller('DetailCtrl', function($scope, Users) {
      $scope.users = Users.get({user_id: $scope.user_id});
    });
    
    //Service
    app.factory('Users', ['$resource', function($resource){
      return $resource('json/users:user_id.json');
    }]);
    Die Routen funktionieren, der ListController fetched per User.query() auch alle Einträge, aber wie mappe im DetailController die user_id des JSON Objekts mit User.get() auf die URL?

  • #2
    Moin,

    du kommst an die jeweiligen Routenparameter durch $routeParams:
    https://docs.angularjs.org/api/ngRou...$route#example

    Kommentar


    • #3
      Danke, aber das alleine löst mein Mapping Problem noch nicht.

      $routeParams liefert war den URL-Parameter, aber wie suche ich damit innerhalb des durch $resource zurückgelieferten JSON nach dem richtigen Objekt?

      Code:
      /* Liefert alle Objekte:
      [
        {"user_id": 1, "user_firstname": "Frank", "user_lastname": "Meier"},
        {"user_id": 2, "user_firstname": "Franziska", "user_lastname": "Schulze"}
      ]
      */
      app.factory('Users', ['$resource', function($resource){
        return $resource('json/users.json);
      }]);
      
      // Soll nur das Objekt mit der user_id analog zu $routeParams liefern
      app.controller('DetailCtrl', function($scope, $routeParams, Users) {
        $scope.users = Users.get({user_id: $routeParams.user_id});
      });

      Kommentar


      • #4
        Du musst auch die get-Route der Ressource entsprechend behandeln.

        Beispielressource /user/:userId

        GET /user sollte alle User zurückgeben.
        GET /user/123 gibt den User 123 zurückgeben.
        POST /user/456 speichert den User 456
        etc.

        Du kannst nicht alles mit einer Datenbasis machen. Serverseitig müssen die unterschiedlichen Routen auch eigens behandelt werden

        Kommentar


        • #5
          Meine Route stimmt: /users/:user_id und $routeParams werden zu /users/1 und "user_id": "1". Auch wenn ich das Beispiel weiter vereinfache
          Code:
          app.controller('DetailCtrl', function($scope, $routeParams, Users) {
            $scope.users = Users.get({user_id: 1});
            console.debug($scope.users);
          });
          erhalte ich in der Konsole ein $resolved: false.

          Was mache ich hier falsch, oder geht es prinzipiell nicht, ein einzelnes Objekt aus einem JSON File zu holen?

          Kommentar


          • #6
            Ich meine, das geht prinzipiell nicht. Ich weiss nicht, ob es dafür vielleicht einen speziellen Konfigurationsparameter gibt. Generell willst du ja auch nicht, dass das so funktioniert. Das würde ja bedeuten, dass du dir immer alle User vom Server ziehen müsstest, um nur einen davon zu tatsächlich zu verarbeiten. Und "speichern" könnte ich mir so gar nicht vorstellen. Das ist schon so gedacht, dass Auflistung und Einzelbetrachtung unterschiedliche Aktionen auf der Serverseite verursachen.

            Wenn du tatsächlich so arbeiten willst, kannst du das auf jeden Fall mit einem Service machen. Da kannst du dann den gerade ausgewählten User hinterlegen und ihn im DetailController wieder abrufen.

            Kommentar


            • #7
              Na gut, wenn das prinzipiell nicht funktioniert, brauche ich es auch gar nicht weiter zu probieren, sondern mache es so wie im offiziellen Angular Tutorial, hinterlege für jeden "Datensatz" ein eigenes JSON File und parametrisiere das im Service.

              Kommentar


              • #8
                Hallöchen,

                du solltest deinen REST-Service so konfigurieren, dass er nur einen User-Datensatz zurückliefert, wenn du bspw. /users/:id ansprichst. Ansonsten könnte man $resource zwar über eine benutzerdefinierte transformResponse-Funktion wie gewünscht hinbiegen, aber das ist de facto die falsche Stellschraube an der du da drehen willst.

                Viele Grüße,
                lotti
                [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

                Kommentar


                • #9
                  Hallo lottikarotti,

                  hast du auch ein Beispiel dafür, wie ich mit .query() alle und bei .parametrisierter URL nur den mit dem entsprechenden $routeParams erhalte? Das hier funktioniert nicht:
                  Code:
                  app.factory('Users', function($resource, $routeParams) {
                    return $resource('json/users.json', {}, {
                      get: {method:'GET', params:{user_id: $routeParams.user_id}, isArray: false}
                    });
                  });

                  Kommentar


                  • #10
                    Er meint, dass du auf der Serverseite nicht einfach für jeden User eine einzelne Datei liegen hast (was an sich ok wäre, wenn die Daten statisch sind), sondern sie durch (bspw. ein PHP-)Script erzeugst, dass auf den :id-Parameter Bezug nimmt. Aus Sicht von Angular:Ressourcen ist PHP nur noch ein Rest-Service.

                    Kommentar


                    • #11
                      Hallöchen,

                      Zitat von Marck Beitrag anzeigen
                      hast du auch ein Beispiel dafür, wie ich mit .query() alle und bei .parametrisierter URL nur den mit dem entsprechenden $routeParams erhalte? Das hier funktioniert nicht:
                      Code:
                      app.factory('Users', function($resource, $routeParams) {
                        return $resource('json/users.json', {}, {
                          get: {method:'GET', params:{user_id: $routeParams.user_id}, isArray: false}
                        });
                      });
                      Das ist ja auch völlig verkehrt. $routeParams hat innerhalb deines Service nichts zu suchen, denn das gehört in den Controller. Dein Service stellt erstmal nur die Schnittstelle zur Verfügung, um generell Daten vom Server abrufen zu können. Wie die Daten abgerufen werden, legst du später während der Verwendung fest, ggf. über festgelegte Methoden und Parameter, je nach Konfiguration. Hier mal ein ganz simples Beispiel:

                      users.php
                      PHP-Code:
                      <?php

                      $users 
                      = [
                          
                      '1' => [
                              
                      'id' => 1,
                              
                      'username' => 'foo',
                          ],
                          
                      '2' => [
                              
                      'id' => 2,
                              
                      'username' => 'bar',
                          ]
                      ];

                      $result null;
                      $id = isset($_GET['id']) ? $_GET['id'] : null;
                      if(
                      $id){
                          if(isset(
                      $users[$id])){
                              
                      $result $users[$id];
                          }
                      } else{
                          
                      $result array_values($users);
                      }

                      header('Content-Type: application/json');
                      echo 
                      json_encode($result);
                      index.html
                      HTML-Code:
                      <!doctype html>
                      <html lang='de' dir='ltr' ng-app='app'>
                      	<head>
                      		<title>$resource usage</title>
                      	</head>
                      	<body ng-controller='AppCtrl'>
                      
                      		<h1>$resource usage</h1>
                      
                      		<h2>a single user object:</h2>
                      		<pre>{{user}}</pre>
                      
                      		<h2>an user array:</h2>
                      		<pre>{{users}}</pre>
                      
                      		<script src='//code.angularjs.org/1.2.26/angular.js'></script>
                      		<script src='//code.angularjs.org/1.2.26/angular-resource.js'></script>
                      		<script>
                      			angular.module('app', ['ngResource'])
                      			.factory('Users', [
                      				'$resource',
                      				function($resource){
                      					return $resource('users.php');
                      				}
                      			])
                      			.controller('AppCtrl', [
                      				'$scope',
                      				'Users',
                      				function($scope, $users){
                      					angular.extend($scope, {
                      						user: $users.get({
                      							id: 1
                      						}),
                      						users: $users.query()
                      					});
                      				}
                      			]);
                      		</script>
                      	</body>
                      </html>
                      Dort wo nun im Controller der Aufruf von $users.get(..) stattfindet, gehört die Id des gesuchten Benutzers hin. In deinem Fall befindet sich diese in $routeParams.id.

                      Viele Grüße,
                      lotti
                      [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

                      Kommentar


                      • #12
                        Danke lotti, das werde ich ausprobieren.

                        Wobei es im vorliegenden Fall reicht, die Übergabe mit JSON Files zu simulieren. Die eigentliche API und das Backend baut jemand anders.

                        Kommentar


                        • #13
                          Hallöchen,

                          Zitat von Marck Beitrag anzeigen
                          Wobei es im vorliegenden Fall reicht, die Übergabe mit JSON Files zu simulieren. Die eigentliche API und das Backend baut jemand anders.
                          Um eine REST-API zu simulieren, liefert AngularJS bereits die notwendigen Tools um diesen Use Case elegant zu lösen: $httpBackend. Nicht vergessen ngMockE2E als Dependency zum App-Module hinzuzufügen.

                          Viele Grüße,
                          lotti
                          [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

                          Kommentar

                          Lädt...
                          X