1

我正在嘗試創建一個簡單的控制面板,它可以模擬here所示的功能。我想堅持一個角度的構想,但我已經成功地把自己搞糊塗了。我對Angular來說很新穎。瞭解角度承諾和API調用 - 從API創建用戶控制面板

我正在創建一個基於Github API數據的簡單儀表板。我想引用下面的數據源(其中用戶是從搜索條和回購值的數值從回購列表點擊 - 見1段聯爲例):

"https://api.github.com/users/" + user       ----> returns general user info 
"https://api.github.com/users/" + user + "/repos"    ----> used for repo list 
"https://api.github.com/repos/" + user + "/" + repo + "/events" ----> list of events per repo 

從本質上講,應用程序應該工作方式如下:

  1. 在搜索欄中輸入用戶名Github上的用戶類型。

  2. 的API調用,以回報用戶信息和回購列表 (前兩個我的網址列)

到目前爲止,我有這方面的工作。

  1. THEN,根據返回的下拉列表中第一個選定的回購或選定的值,第三個url將被調用以返回更多數據。

據我所知,我需要合併Angular promises,因爲我的3rd Get請求沒有被識別。

有人可以幫助我調整自己的app.js代碼,以確保: - 我有頁上的一組「回購」呈現(即第一上市回購將被默認選中) - 事件API又被稱爲在用戶與回購清單交互後

我試圖按照here的說明進行操作,但我對如何合併用戶名和所選回購存在一些困惑。如果有人能夠引導我如何在代碼中添加這些參數(由用戶指定),我將非常感激!

這裏是我當前的代碼,以供參考:

app.js

angular.module('myApp', ['ui.router']) 
    .controller('DashboardCtrl', function($scope, $state, $http){ 
     // Set search model to 'mbostock' and the fetch function to contact the 
     // remote API and ensure the view is initialized. Load results when the search box changes. 
     $scope.$watch('search', function() { 
      initialFetch(); 
     }); 
     $scope.search = "mbostock"; 


    // Make calls to the API for Users and Repo List 
    function initialFetch(){ 
     $http.get("https://api.github.com/users/" + $scope.search) 
      .then(function(response){ $scope.userinfo = response.data; }); 

     $http.get("https://api.github.com/users/" + $scope.search + "/repos") 
      .then(
       function(response){ $scope.repolist = response.data; 

       // Create call for events listing based on repo choice 
       var repo = ""; 

       // console.log(document.getElementById("repo1").value); 

       $(function() { 
        //For showing default url 
        MakeUrl(); 
        // On repository selection, call events 
        $('#repo-select').on('change', function() { 
         if ($(this).val() == 0) { 
          repo = document.getElementById("repo1").value; 
         } else { 
          repo = $(this).val(); 
         } 
         MakeUrl(); 
         return false; 
        }); 

       }); 

       function MakeUrl() { 
        var finalUrl = "https://api.github.com/repos/" + $scope.search + "/" + repo + "/events"; 
        console.log(finalUrl); 
        $http.get(finalUrl) 
         .then(function (response) { $scope.eventinfo = response.data; }); 
       } 


       }); 
    } 


    // Function select which ensures that the entire 
    // text is selected when the user clicks in the text input. 
    $scope.select = function(){ 
     this.setSelectionRange(0, this.value.length); 
    } 
}) 

的index.html

<body> 
<div class="container-fluid outerdiv" ng-app="myApp" ng-controller="DashboardCtrl"> 

    <nav class="navbar navbar-inverse navbar-fixed-top"> 
     <div class="container-fluid"> 
      <div class="navbar-header"> 
       <a class="navbar-brand"><b>Github User Information</b> <span class="span-style"></span></a> 
      </div> 

      <div class="input-group search-bar"> 
       <input type="text" ng-model="search" ng-model-options="{ debounce: 800 }" onclick="select()" class="form-control" placeholder="Enter Github user login" autofocus /> 
       <span class="input-group-addon bar-style"><i class="glyphicon glyphicon-search"></i></span> 
      </div> 
     </div> 
    </nav> 

    <noscript> 
     <div class="nojs">Javascript is either disabled or not supported in your browser. Please enable it or use a Javascript enabled browser.</div> 
    </noscript> 

    <div class="animated zoomInRight"> 


     <div id="user-bio" class="col-sm-4 col-md-4"> 
      <div> 
       <div class="avatar"> 
        <img src="{{ userinfo.avatar_url }}" class="thumbnail animated flip movie-poster"> 
       </div> 

       <span class="span-outer"> 
        <a href="{{userinfo.html_url}}" target="_blank">{{ userinfo.login }}</a> 
       </span><br>{{ userinfo.name }} 

       <p><strong>Joined:</strong><br> {{ userinfo.created_at }}</p> 
       <p><strong>Last Updated:</strong><br> {{ userinfo.updated_at }}</p> 

       <p>{{ userinfo.bio }}</p> 

       <p class="outer-p"> 
       <div class="inner-p"> 
        <span class="label label-primary">Public Repos :</span> {{ userinfo.public_repos }} 
       </div> 
       <div class="inner-p"> 
        <span class="label label-primary">Followers :</span> {{ userinfo.followers }} 
       </div> 
       <div class="inner-p"> 
        <span class="label label-primary">Following :</span> {{ userinfo.following }} 
       </div> 
       </p> 

      </div> 

      <div ng-if="userinfo.message==='Not Found'"> 
       No results found. 
      </div> 
     </div> 

     <div class="col-sm-8 col-md-8"> 
      <h5><strong>Repositories:</strong></h5> 
      <select id="repo-select"> 
       <option ng-repeat="repo in repolist" id="repo{{ $index + 1 }}" value="{{ repo.name }}" onchange="MakeUrl();">{{ repo.name }}</option> 
      </select> 

      <h5><strong>Events:</strong></h5> 
      <ul class="event-results" id="event-select" style="height:400px; overflow-y:auto;"> 
       <li ng-repeat="event in eventinfo"> 
        <a id="{{ $index + 1 }}" value="{{ event.type }}">{{ event.type }} 
        </a>, {{ event.created_at }} <!--ng-click="update(movie)"--> 
       </li> 
      </ul> 
     </div> 

    </div> 
</div> 

</body> 

編輯 這裏是我的錯誤再見,它們看起來像是秈稻我需要履行承諾。然後再次,我不知道爲什麼我不能指定默認選定的回購。{「data」:{「message」:「找不到」,「documentation_url」:「https://developer.github.com/v3」},「status」:404,「config」:{「method」:「GET」 ,「transformRequest」:[null],「transformResponse」:[null],「jsonpCallbackParam」:「callback」,「url」:「https://api.github.com/repos/mbostock//events」,「headers」:{「Accept」:「application/json,text/plain ,/ 「}},」 狀態文本 「:」 未找到「}

更新和編輯 通過@mikwat的建議下,我嘗試使用NG-模型來回購變量綁定。

我的新app.js文件看起來像這樣:

​​3210

雖然這是獲取數據來呈現,我無法弄清楚如何動態地分配一號回購列表值設爲默認值(我試過document.getElementById("repo1").value但我得到了'未定義')並且該函數不會在下拉更改時再次調用API。

UPDATE 2017/5/5 - 個人解決方案 非常感謝@mikwat的所有幫助。我最終使用了一種與以下不同的解決方案,但兩者都起作用。

angular.module('myApp', []) 
.controller('DashboardCtrl', function($scope, $http){ 
    // Set search model to 'mbostock' and the fetch function to contact the 
    // remote API and ensure the view is initialized. Load results when the search box changes. 
    $scope.$watch('search', function() { 
     initialFetch(); 
     // .then(MakeUrl); 
    }); 

    // NOTE: watch for changes to repo 
    $scope.$watch('repo', function() { 
     $http.get("https://api.github.com/repos/" + $scope.search + "/" + $scope.repo + "/events") 
      .then(function (response) { 
       $scope.eventinfo = response.data; 
      }); 

    }); 

    var user = $scope.search; 
    $scope.search = "mbostock"; 

    // Make calls to the API for Users and Repo List 
    function initialFetch(){ 
     $http.get("https://api.github.com/events") 
      .then(function(response){ $scope.publicevents = response.data; console.log(response.data);}) 
      .catch(function (err) { 
         console.log(err) 
        }); 

     $http.get("https://api.github.com/users/" + $scope.search) 
      .then(function(response){ $scope.userinfo = response.data; }) 
      .catch(function (err) { 
         console.log(err) 
        }); 

     $http.get("https://api.github.com/users/" + $scope.search + "/repos") 
      .then(
       function(response){ 
        $scope.repolist = response.data; 

        // NOTE: select first repo 
        if ($scope.repolist && $scope.repolist.length > 0) { 
         var repo = $scope.repolist[0].name; 
        } else { 
         console.log("Something went wrong here!"); 
         var repo = "undefined" 
        } 
        $scope.repo = repo; 
        return repo 
       }).then(function (repo) { 
         $http.get("https://api.github.com/repos/" + $scope.search + "/" + repo + "/events") 
         .then(function (response) { $scope.eventinfo = response.data; console.log(response.data);}) 
         return repo; 
        }).then(function (repo) { 
         $http.get("https://api.github.com/repos/" + $scope.search + "/" + repo + "/languages") 
         .then(function (response) { $scope.languages = response.data; console.log(response.data);}) 
        }).catch(function (err) { 
         console.log("Here!" + err); 
        }); 
    }; 


    // Function select which ensures that the entire 
    // text is selected when the user clicks in the text input. 
    $scope.select = function(){ 
     this.setSelectionRange(0, this.value.length); 
    } 


}); 
+0

它看起來像你調用'的https:// api.github.com /回購/ mbostock // events',而不是'https://api.github.com/ repos/mbostock/preamble/events'(例如)。嘗試使用Angular的'ng-model'選擇模塊,而不是嘗試在jQuery中混合使用:https://docs.angularjs.org/api/ng/directive/select – mikwat

+0

@mikwat感謝您的提示!當你提出這個問題時,我已經開始朝着這個方向前進。它絕對讓我前進,但我仍然有問題(請參閱我的主要問題中的「更新和編輯」部分)。 – KateJean

+0

好吧,我想我有一個適合你的工作解決方案。看到我的帖子下面。 – mikwat

回答

1

下面是一個工作解決方案。我刪除了一些依賴關係,只是爲了讓它在這個沙箱中工作。我使用NOTE:評論來幫助描述重要變化。

angular.module('myApp', []) 
 
    .controller('DashboardCtrl', function($scope, $http){ 
 
     // Set search model to 'mbostock' and the fetch function to contact the 
 
     // remote API and ensure the view is initialized. Load results when the search box changes. 
 
     $scope.$watch('search', function() { 
 
      initialFetch(); 
 
       // .then(MakeUrl); 
 
     }); 
 
     
 
     // NOTE: watch for changes to repo 
 
     $scope.$watch('repo', function() { 
 
      $http.get("https://api.github.com/repos/" + $scope.search + "/" + $scope.repo + "/events") 
 
       .then(function (response) { 
 
        $scope.eventinfo = response.data; 
 
        }); 
 
        
 
      // NOTE: additional request to fetch languages 
 
      $http.get("https://api.github.com/repos/" + $scope.search + "/" + $scope.repo + "/languages") 
 
       .then(function (response) { 
 
        console.log(response.data); 
 
        // TODO: display results 
 
        }); 
 

 
     }); 
 

 
     var user = $scope.search; 
 
     $scope.search = "mbostock"; 
 

 
     // Make calls to the API for Users and Repo List 
 
     function initialFetch(){ 
 
      $http.get("https://api.github.com/users/" + $scope.search) 
 
       .then(function(response){ $scope.userinfo = response.data; }); 
 

 
      $http.get("https://api.github.com/users/" + $scope.search + "/repos") 
 
       .then(
 
        function(response){ 
 
         $scope.repolist = response.data; 
 
         
 
         // NOTE: select first repo 
 
         if ($scope.repolist && $scope.repolist.length > 0) { 
 
          $scope.repo = $scope.repolist[0].name; 
 
         } 
 
        }, 
 
        $http.get("https://api.github.com/repos/" + $scope.search + "/" + $scope.repo + "/events") 
 
         .then(function (response) { $scope.eventinfo = response.data; }) 
 
       ); 
 
     } 
 

 

 
     // Function select which ensures that the entire 
 
     // text is selected when the user clicks in the text input. 
 
     $scope.select = function(){ 
 
      this.setSelectionRange(0, this.value.length); 
 
     } 
 
    });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<div class="container-fluid outerdiv" ng-app="myApp" ng-controller="DashboardCtrl"> 
 

 
    <nav class="navbar navbar-inverse navbar-fixed-top"> 
 
     <div class="container-fluid"> 
 
      <div class="navbar-header"> 
 
       <a class="navbar-brand"><b>Github User Information</b> <span class="span-style"></span></a> 
 
      </div> 
 

 
      <div class="input-group search-bar"> 
 
       <input type="text" ng-model="search" ng-model-options="{ debounce: 800 }" onclick="select()" class="form-control" placeholder="Enter Github user login" autofocus /> 
 
       <span class="input-group-addon bar-style"><i class="glyphicon glyphicon-search"></i></span> 
 
      </div> 
 
     </div> 
 
    </nav> 
 

 
    <noscript> 
 
     <div class="nojs">Javascript is either disabled or not supported in your browser. Please enable it or use a Javascript enabled browser.</div> 
 
    </noscript> 
 

 
    <div class="animated zoomInRight"> 
 

 

 
     <div id="user-bio" class="col-sm-4 col-md-4"> 
 
      <div> 
 
       <div class="avatar"> 
 
        <img src="{{ userinfo.avatar_url }}" class="thumbnail animated flip movie-poster"> 
 
       </div> 
 

 
       <span class="span-outer"> 
 
        <a href="{{userinfo.html_url}}" target="_blank">{{ userinfo.login }}</a> 
 
       </span><br>{{ userinfo.name }} 
 

 
       <p><strong>Joined:</strong><br> {{ userinfo.created_at }}</p> 
 
       <p><strong>Last Updated:</strong><br> {{ userinfo.updated_at }}</p> 
 

 
       <p>{{ userinfo.bio }}</p> 
 

 
       <p class="outer-p"> 
 
       <div class="inner-p"> 
 
        <span class="label label-primary">Public Repos :</span> {{ userinfo.public_repos }} 
 
       </div> 
 
       <div class="inner-p"> 
 
        <span class="label label-primary">Followers :</span> {{ userinfo.followers }} 
 
       </div> 
 
       <div class="inner-p"> 
 
        <span class="label label-primary">Following :</span> {{ userinfo.following }} 
 
       </div> 
 
       </p> 
 

 
      </div> 
 

 
      <div ng-if="userinfo.message==='Not Found'"> 
 
       No results found. 
 
      </div> 
 
     </div> 
 

 
     <div class="col-sm-8 col-md-8"> 
 
      <h5><strong>Repositories:</strong></h5> 
 
      
 
      <!-- NOTE: use ng-model and ng-repeat and don't clobber repo variable on scope --> 
 
      <select id="repo-select" ng-model="repo"> 
 
       <option ng-repeat="r in repolist" id="repo{{ $index + 1 }}" ng-value="r.name" onchange="MakeUrl();">{{ r.name }}</option> 
 
      </select> 
 

 
      <h5><strong>Events:</strong></h5> 
 
      <ul class="event-results" id="event-select" style="height:400px; overflow-y:auto;"> 
 
       <li ng-repeat="event in eventinfo"> 
 
        <a id="{{ $index + 1 }}" value="{{ event.type }}">{{ event.type }} 
 
        </a>, {{ event.created_at }} <!--ng-click="update(movie)"--> 
 
       </li> 
 
      </ul> 
 
     </div> 
 

 
    </div> 
 
</div>

+0

你是一個救星!謝謝!你的評論確實幫助我理解你的過程。 就可擴展性而言 - 我將如何根據回購和搜索值來製作另一個GET請求(如最後的GET請求是?即「api.github.com/repos/」; + $ scope.search +「/」+ $ scope.repo +「/ languages」)我擔心我的原始構造不容易擴展,因此我的問題很早就引用了Angular承諾 - 鏈接 – KateJean

+0

我不認爲有任何需要承諾如果您希望在選擇回購時進行額外的API調用,則需要進行鏈接。看到我更新的答案。 '$ http.get'調用將運行異步,所以也沒有真正的縮放問題。我錯過了什麼嗎? – mikwat

+0

不,這絕對有效!我最終弄清楚了昨晚如何做到這一點,雖然不像你那麼簡單!我很感激你花時間回覆。 有關我的解決方案,請參閱我的更新問題。 – KateJean