首页 文章

了解Angular Promises和API调用 - 从API创建用户仪表板

提问于
浏览
1

我正在尝试创建一个模仿here所示功能的简单仪表板 . 我成功地把自己弄成了遗忘 . 一般来说,我对Angular很新 .

我正在基于Github API的数据创建一个简单的仪表板 . 我想引用以下数据源(其中 user 是搜索栏中的值, repo 是从回购列表中单击的值 - 请参阅第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

从本质上讲,应用程序应该按以下方式工作:

  • 用户在搜索栏中输入Github用户名 .

  • 进行API调用以返回用户信息和回购列表(我列出的前两个网址)

到目前为止,我有这个工作 .

  • 然后,根据返回的下拉列表中的第一个选定的repo或所选的值,将调用第3个url以返回更多数据 .

据我所知,我需要加入Angular承诺,因为我的第3次Get请求未被识别 .

有人可以帮我重构我的app.js代码以确保: - 我在页面渲染上设置了一个“repo”(即第一个列出的repo将是默认选择) - 在用户与repo交互后再次调用事件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>

EDIT 这是错误我'm seeing -- again, they seem to indicate I need to implement promises. Then again, I'我不知道为什么我不能指定默认的选定仓库 .

可能未处理的拒绝:{"data":{"message":"Not Found","documentation_url":” https://developer.github.com/v3 "},"状态":404,"配置":{"方法":" GET "," transformRequest ":[null]," transformResponse ":[null]," jsonpCallbackParam ":"回调","网址":" https://api.github.com/repos/mbostock//events ","头":{"接受":"应用/ JSON,纯文本/,/ "}}," statusText ":" Not Found“}

UPDATE AND EDIT 通过@mikwat的建议,我尝试使用ng-model来绑定repo变量 .

我的新app.js文件如下所示:

angular.module('myApp', ['ui.router'])
    .controller('DashboardCtrl', function($scope, $state, $http, DataService){
        // 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);
        });

        var user = $scope.search;
        $scope.search = "mbostock";
        $scope.repo = "array-source";


        // 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; },
                    $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);
        }
    });

虽然这是要渲染数据,但我无法弄清楚如何动态分配第一个repo列表值作为我的默认值(我试过 document.getElementById("repo1").value 但我得到'undefined')并且该功能在下拉列表更改时不会再次调用API .

UPDATE 5/5/2017 -- Personal Solution 非常感谢@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);
    }


});

1 回答

  • 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>
    

相关问题