8
respostas

AngularJS uso de funçoes com services

Olá, eu encontrei alguns tutoriais e estava tentando criar meus próprios services e chamar no controller, mas ainda tenho dificuldades com funções e passagem de parâmetros.

Eu entendi como funciona os exemplos, mas eu não consegui dividir o que é do controller e o que faz parte do service.

A função $scope.getYoutubeData faz a requisição e depois é chamada na função que carrega os próximos resultados:

 $scope.callNextPageFn = function(nextPage){
        $scope.nextPage = nextPage;        
        $scope.getYoutubeData($scope.youtubeSearchText);

    };

Esse exemplo é do controller que funciona:

app.controller('youtubeController', function($scope,$http,$filter) {
    $scope.youtubeData = [];
    $scope.nextPage = "";
    $scope.youtubeSearchText = "";
    $scope.getYoutubeData = function(searchText){
        $http.get('https://www.googleapis.com/youtube/v3/search', {
            params: {
                key: "API Key",
                part: 'contentDetails',
                type: 'video',
                maxResults: '12',
                pageToken: $scope.nextPage ? $scope.nextPage : '',
                part: 'id,snippet',                
                fields: 'items/id,items/snippet/title,items/snippet/description,items/snippet/thumbnails/default,items/snippet/channelTitle,nextPageToken,prevPageToken',
                q: 'searchText'
            }
        }).success( function (data) {
            if (data.items.length === 0) {
                $scope.youtubeData = 'No results were found!';
            }
            $scope.youtubeSearchText = searchText;
            $scope.youtubeData = data.items;
            console.log(data.items);
            $scope.nextPageToken = data.nextPageToken;
            $scope.prevPageToken = data.prevPageToken;
        });
    };

    $scope.checkDataLength = function(data){
        return (data.length >=1);
    };

    $scope.callNextPageFn = function(nextPage){
        $scope.nextPage = nextPage;        
        $scope.getYoutubeData($scope.youtubeSearchText);

    };

});

Essa é a tentativa de dividir:

app.controller('ListaVideos', []);
        var channelId = 'UC2pmfLm7iq6Ov1UwYrWYkZA';        
        var key = 'APl Key';

        app.factory('youtubeService', ['$http', function ($http) {           
            function getPlaylistItems(id) {
                 return $http.get('https://www.googleapis.com/youtube/v3/playlistItems', { 
                  params: { 
                    part: 'snippet',                                     
                    playlistId: id,
                    key: key,                 
                  }
                });
            }
            return { 
              getPlaylistItems: getPlaylistItems
            }
        }]);

  app.controller('VideoPlayerController', ['$http','$scope','youtubeService', function ($http, $scope, youtubeService) {
          $scope.youtubePlaylist = [];        
          youtubeService.getPlaylistItems('PLhEguvmo7mSPjBv1XHxJn7A3zHLFTLSFT')
          .then(function (response) {    
               console.log(response.data.items)                           

               $scope.youtubePlaylist = response.data.items;
               $scope.nextPageToken = response.data.nextPageToken;                
              })


               $scope.checkDataLength = function(data){
                return (data.length >=1);
               };

             $scope.callNextPageFn = function(nextPage){
            $scope.nextPageToken  = nextPage;
               console.log(nextPage);
              console.log(youtubeService.getPlaylistItems('PLhEguvmo7mSPjBv1XHxJn7A3zHLFTLSFT'));   

           };

O que acontece, eu tentei repetir a função scope.getYoutubeData($scope.youtubeSearchText) com youtubeService.getPlaylistItems('PLhEguvmo7mSPjBv1XHxJn7A3zHLFTLSFT'), mas eu vi que não é a mesma coisa, porque isso retorna outra coisa.

Eu entendi errado? A função youtubeService.getPlaylistItems não faz o mesmo que scope.getYoutubeData?

Eu acho que o que tem que ficar no service é a parte da requisição, não? Mas e depois para chamar no controller?

No youtubeController ele só lista se passar um valor no input, como eu listo um resultado aleatório pra não deixar vazio, porque eu tentei executar a função $scope.getYoutubeData('alguma palavra chave') que lista e depois a busca não funcionava mais, se a pessoa digitasse.

8 respostas

Gisele boa tarde, veja se isso te atende

HTML

<html>
    <head>
        <meta charset="UTF-8">
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.3/angular.min.js"></script>
    </head>
    <body>
        <div ng-app="app" ng-controller="myCtrl">
                <div>
                    <input type="number" ng-model="numeroPost" />
                    <button ng-click="changePost()">Change</button>
                </div>
                <div>
                    <h1>Titulo: {{posts.title}}</h1>
                    <label>Descrição: </label>
                    <p>{{posts.body}}</p>
                </div>


        </div>

Javascript

<script>
            var app = angular.module("app", []);


            app.factory('restService', ['$http', function ($http) {
            return {
                getPost: function(id){
                    console.log("Recebi o parametro ", id)
                     return $http.get('https://jsonplaceholder.typicode.com/posts/'+id).then(function(response){
                        return response.data;
                    })
                }
            }
            }]);


            app.controller("myCtrl", function($scope, restService) {
                //$scope.posts = restService.getPost();
                //Carregamento inicial
                $scope.numeroPost = 1;

                (    $scope.changePost = function(){
                        restService.getPost($scope.numeroPost).then(function(posts){
                            $scope.posts = posts;
                    })
                })();

            });
        </script>

Obrigada.

Acho que o problema é na minha função que retorna os resultados, de novo o response.data.nextPageToken, que devolve o mesmo resultado.

Criei no code pen para visualizar, esse primeiro código eu peguei de um tutorial, mas estou fazendo modificações.

Tenho 2 dúvidas:

Sobre o escopo das funções, a $scope.getYoutubeData = function(searchText). Sei que searchText é o termo digitado no formulário e preenchendo com os dados da API quando eu aperto Enter no teclado e quando eu clico no botão, preenche a view com o nextPageToken.

Então eu tentei fazer o mesmo usando youtubeService.getPlaylistItems('PLhEguvmo7mSPjBv1XHxJn7A3zHLFTLSFT'), mas o resultado não foi o mesmo.

Porque?

A view da busca não recarrega se eu mudo o termo da busca, a ideia era usar um botão, que clica e busca ao invés do enter.

Codepen da busca:

http://codepen.io/Gisesonia/pen/jBRMrG

Codepen da lista com o service (não sei porque não carregou direito, mas na minha máquina está funcionando):

http://codepen.io/Gisesonia/pen/OpGRzp

Neste seu serviço youtubeService, onde você criou o método getPlaylistItems, este método recebe apenas um parâmetro, que é o ID.

No controller onde você está consumido ele (VideoPlayerController), você está executando o método ao abrir, e criando uma função callNextPageFn. Apesar desta função de próxima página receber o token da página seguinte, você não está enviando para o serviço. Teria que alterar para algo assim:

  $scope.callNextPageFn = function(nextPage){

               console.log(nextPage);
              console.log(youtubeService.getPlaylistItems('PLhEguvmo7mSPjBv1XHxJn7A3zHLFTLSFT', nextPage));   

           };

E alterar o método no serviço para receber mais um parâmetro:

app.factory('youtubeService', ['$http', function ($http) {           
            function getPlaylistItems(id, pagina_selecionada) {
                var opcoes = { 
                    part: 'snippet',                                     
                    playlistId: id,
                    key: key,                 
                  };

                   if (pageToken !== null){
                        opcoes.pageToken = pagina_selecionada;
                    }


                 return $http.get('https://www.googleapis.com/youtube/v3/playlistItems', { 
                  params: opcoes;
                });
            }
            return { 
              getPlaylistItems: getPlaylistItems
            }
        }]);

No primeiro código postado, o do controller youtubeController, tem uma função de próxima página

 $scope.callNextPageFn = function(nextPage){
        $scope.nextPage = nextPage;        
        $scope.getYoutubeData($scope.youtubeSearchText);

    };

O código somente vai funcionar se o valor passado como parâmetro for o conteúdo recuperado na parte de sucesso da função getYoutubeData (variável $scope.nextPageToken).

Se esta variável for usada no link que chama a função, vai funcionar e trazer uma página nova, caso contrário, qualquer chamada do link de nova página vai receber como parâmetro um valor vazio, então sempre vai carregar a mesma página de resultados.

Obrigada, minha dúvida é nas funções mesmo e passagem de parametro.

Isso if (pageToken !== null){ opcoes.pageToken = pagina_selecionada; } é o mesmo que isso, não? pageToken: nextPage ? nextPage : '',

Eu tentei colocar $scope na factory para colocar pageToken: $scope.nextPage ? $scope.nextPage : '', mas teve erro de injeção de dependência

Eu entendi que vem da lista que está sendo carregada, mas não funcionou, tem a ver com esse parte? A requisição é feita na factory e o resultado na controller? Não sei se estou puxando os resultados da forma correta.

Essa função do youtube factory me retorna isso:

e {$$state: Object}$$state: Objectstatus: 1value: Objectconfig: Objectdata: Objectheaders: function (d)status: 200statusText: ""proto: Objectproto: Objectproto: Object

app.controller('ListaVideos', []);
        var channelId = 'UC2pmfLm7iq6Ov1UwYrWYkZA';        
        var key = 'AIzaSyD_lkEhV8vykZJxcInp1eV83JNR_3plGrQ';       
        var pageToken = ''; 
        app.factory('youtubeService', ['$http', function ($http) {         
            function getPlaylistItems(id, pagina_selecionada) {
                var opcoes = { 
                    part: 'snippet',                                     
                    playlistId: id,
                    key: key,                 
                  };

                   if (pageToken !== null){
                        opcoes.pageToken = pagina_selecionada;
                    }


                 return $http.get('https://www.googleapis.com/youtube/v3/playlistItems', { 
                  params: opcoes
                });
            }
            return { 
              getPlaylistItems: getPlaylistItems
            }
        }]);

app.controller('VideoPlayerController', ['$http','$scope','$uibModal','$sce','youtubeService', '$log', function ($http, $scope,$uibModal, $sce, youtubeService,$log) {

        $scope.youtubePlaylist = [];         
        $scope.aceitaUrl = function(video) {                  
                return $sce.trustAsResourceUrl(video);//cuida da parte de autorização Cross Origin                
              }   

          youtubeService.getPlaylistItems('PLhEguvmo7mSPjBv1XHxJn7A3zHLFTLSFT', 'CAUQAA')
          .then(function (response) { 

               $scope.youtubePlaylist = response.data.items;
               $scope.nextPageToken = response.data.nextPageToken; 
               console.log($scope.nextPageToken);          
              });        

               $scope.checkLength = function(data){
                return (data.length >=1);
                   console.log(data);
               };

      $scope.divHtmlVar = '';
              $scope.carregaMais = function(nextPage) {
                  $scope.nextPageToken  = nextPage;
                  $scope.divHtmlVar = $scope.divHtmlVar + '<br/><i>'+nextPage+'</i>';  
                  console.log(nextPage); console.log(youtubeService.getPlaylistItems('PLhEguvmo7mSPjBv1XHxJn7A3zHLFTLSFT', nextPage));   
              }
 $scope.callNextPageFn = function(nextPage){
        $scope.nextPage = nextPage;        
        $scope.getYoutubeData($scope.youtubeSearchText);

    };

Dessa forma está funcionado, o botão next, carrega os resultados, o problema é quando eu digito algo na busca ele carrega, mas se eu apagar e digitar outra coisa e buscar não carrega o que eu digitei de diferente.

Acho que o meu erro está no Javascript e alguma função que estou carregando os dados de forma errada, mas não estou conseguindo achar o erro.

Esse é o link do tutorial, está dividido em vários arquivos, mas eu juntei tudo no codepen, a diferença é que ele recarrega os resultados no ng-change e eu quero mudar para um click de botão e eu queria listar alguns resultados antes de clicar:

Tutorial: http://www.w3tweaks.com/youtube/angularjs-instant-youtube-video-search-api-v3-version-tutorial.html

Exemplo funcionando: http://www.w3tweaks.com/demo/angularjs_instant_youtube_video_search_api_v3/#/home

Código atualizado:

http://codepen.io/Gisesonia/pen/OpGRzp

Ainda não descobri porque a variável nextTokenPage não atualiza, deve ser algo de escopo, porque no exemplo que funciona a resposta e requisição estão na mesma função.

Quando clica no botão carregar mais, tem que fazer outra requisição e adicionar os resultados no array $scope.youtubePlaylist?

O angularjs, não deixa fazer append desse jeito, que dá erro Error: [$sanitize:badparse]:

 $scope.divHtmlVar = $scope.divHtmlVar + '<div class="col-xs-12 col-sm-8 col-md-4 col-lg-6"><a href="#"><img class="img-responsive" ng-show="true" src=' +$scope.thumb+ 'alt="Video Image"><br/><i>'+nextPage+'</i>';

Atualizado, agora carrega os videos, só colocar API Key:

http://codepen.io/Gisesonia/pen/OpGRzp

Consegui fazer carregar mais vídeos, não sei se ficou o código ideal, mas funcionou, único problema é que quando ele chega em um nextPageToken undefined, ele começa a repetir a lista ou tem algo errado no código...

O que eu fiz de diferente foi isso, na função do botão, não sei se foi o certo:

             nextPage = response.nextPageToken;
             $scope.nextPageToken = nextPage;

Segue o código adicionando videos na lista com o botão carregar mais:

http://codepen.io/Gisesonia/pen/oWgBEg?editors=1111