angularjs - 如何使用 AngularJS/Web API/Angular-ui-router 在指令中调用 $http.put 服务后更新页面

标签 angularjs asp.net-web-api angularjs-directive angularjs-scope angular-bootstrap

我们是 AngularJS 的新手,但正在开发一个 AngularJS/Web API 应用程序,该应用程序从 AngularJS Bootstrap popover 更新数据模型/指示。

我们已经成功地从指令/弹出窗口更新了数据库,但是在弄清楚如何在不重新加载页面的情况下使用更新后的数据刷新页面上的数据时遇到了麻烦。

主页 CSHTML:

<div ng-app="FFPA" ng-controller="myCtrl">
   <div svg-floorplan="dataset"></div>
</div>

弹出 HTML:
<div>
   <div>
      ID: {{ person.Id }}<br />
      Name: {{ person.fullName }}<br />
      Current Cube/Office: {{ person.seatId }}
      <br />
      Dept: {{ person.deptId }}
      <br />
      Job Desc: {{ person.jobDesc}}
      <br />
      Phone:{{ person.phone}}
      <br />
      <!--<input type="button" value="Click Me" ng-click="changeName()">-->
   </div>
   <div class="hiddenDiv" ng-hide="toggle">
      <div class="form-group">
         <label for="floor">Floor</label>
         <input id="floor" ng-model="person.floor" type="text" ng-trim="true"  class="form-control" />
      </div>
      <div class="form-group">
         <label for="section">Section</label>
         <input id="section" ng-model="person.section" ng-trim="true" type="text" class="form-control" />
      </div>
      <div class="form-group">
         <label for="offCubeNum">offCubeNum</label>
         <input id="offCubeNum" ng-model="person.offCubeNum" ng-trim="true" type="text" class="form-control" />
      </div>
      <div class="form-group">
         <label for="cbCube">Cubicle?</label>
         <input id="cbCube" ng-model="person.cbCube" type="checkbox" size="1" class="checkbox" />
      </div>
   </div>
   <div ng-hide="buttonToggle">
      <input type="button" value="Move" class="btn btn-success" ng-click="moveEmp()">
      <input type="button" value="Term" class="btn btn-danger" ng-click="changeName()">
   </div>
   <div ng-hide="submitToggle">
      <input type="button" value="Submit" class="btn btn-success" ng-click="submitMove()">
      <input type="button" value="Cancel" class="btn btn-warning" ng-click="cancel()">
   </div>
</div>

主页最初从 angular Controller 中的服务获取数据:
var app = angular.module('FFPA', ['ngAnimate', 'ngSanitize', 'ui.bootstrap', 'ui.router']);
    app.controller('myCtrl', function ($scope, dataService) {
    $scope.test = 'test';
        dataService.getData().then(function (data) {
            //The reduce() method reduces the array to a single value.
            $scope.dataset = data.reduce(function (obj, item) {
                obj[item.seatId.trim()] = item;
                item.fullName = item.fName + ' ' + item.lName;
                item.deptId = item.deptId;
                item.jobDesc = item.jobDesc;
                item.phone = item.phone;

                return obj;

            }, {});
        });
    });

获取数据服务:
    angular.module('FFPA').service('dataService', function ($http) {
    this.getData = function () {
        //web api call
        return $http.get("api/Controller/GetData).then(
          function (response) {
              return response.data;
          }, function () {
              return { err: "could not get data" };
          }
        );
    }
});

从 Popover 指令调用更新服务。

更新服务:
    angular.module('FFPA').service('updateService', function ($http) {
    this.putData = function (oc) {

        //web api call
        return $http.put("api/Controller/PutUpdateData", oc).then(
          function (response) {

              return response.data;
          }, function () {
              return { err: "could not update data" };
          }
        );
    }
});

这是我们的 Popover 指令的一个片段,其中发生了更新,我们认为可以刷新范围和页面数据的位置:
updateService.putData(data).then(function (response) {
   if (response == false)
    alert("Move Failed!");
   else {
    alert("Move Succeeded.");
    //$window.location.reload() causes a page reload..not desirable
    //$window.location.reload();
     $state.reload();
}
});

我们尝试了 $state.reload();在 updateService.putData(data) 之后的 popover 指令中,但这会导致 -> 错误:无法转换到抽象状态 '[object Object]' 错误。

这是完整的 Popover 指令:
angular.module('FFPA').directive('svgFloorplanPopover', ['$compile', 'updateService', 'vacancyService', 'addService', 'terminateService', '$window', '$state', function ($compile, updateService, vacancyService, addService, terminateService, $window, $state) {
return {
    restrict: 'A',
    scope: {
        'person': '=svgFloorplanPopover',
         //UPDATE 8-MAY-2017
         onDataUpdate: '&'
    },
    link: function (scope, element, attrs) {
        scope.moveToggle   = true;               //hide move toggle
        scope.addToggle    = true;                //hide add toggle
        scope.submitToggle = true;             //hide submit toggle


        scope.$watch("person", function () {
            if (scope.person) {
                if (scope.person.vacant == true) {
                    scope.addToggle         = false;  //show add button
                    scope.empInfoToggle     = true;   //hide emp info
                }
                else
                    scope.moveToggle = false; //show move
            }
        });

        //add employee---------------------------------------------------------
        scope.addEmp = function () {
            scope.addToggle = scope.addToggle === false ? true : false;

            scope.buttonToggle = true;
            scope.submitToggle = false;

            var data = {
                deptId: scope.person.deptId,
                divisionId: scope.person.divisionId,
                empId: scope.person.empId,
                floor: scope.person.floor,
                fName: scope.person.fName,
                lName: scope.person.lName,

                jobDesc: scope.person.jobDesc,
                officeCode: scope.person.officeCode,
                phone: scope.person.phone,
                section: scope.person.section,
                seat: scope.person.seat,
                seatId: scope.person.seatId,
                seatTypeId: scope.person.seatTypeId,
                vacant: scope.person.vacant
            };


            //call to update/move the employee 
            //updateService.putData(scope.person).then(function () {
            addService.putData(data).then(function (response) {
                if (response == false)
                    alert("Create Failed!");
                else {
                    alert("Create Succeeded.");
                      //UPDATE 8-MAY-2017
                      $scope.onDataUpdate({ person: $scope.person, moreData: $scope.moreData });
                    //$window.location.reload();
                    //$route.reload();
                    //scope.toggle = false;
                }
            });
        }


        //cancel function---------------------------------------------------------
        scope.cancel = function () {}

        //Term emp---------------------------------------------------------
        scope.termEmp = function () {
            var data = {
                seatId: scope.person.seatId,
                floor: scope.person.floor
            };
            terminateService.putData(data).then(function (response) {
                if (response == false)
                    alert("Term Failed!");
                else {
                    alert("Term Succeeded.");
                    $window.location.reload();
                    //$route.reload();
                    //scope.toggle = false;
                }

            });
        }


        //move employee---------------------------------------------------------
        scope.moveEmp = function () {
            scope.toggle = scope.toggle === false ? true : false;
            scope.buttonToggle = true;
            scope.submitToggle = false;
            if (scope.person && scope.person.fullName.indexOf('changed') === -1) {
                //scope.person.fullName += ' move?';
            }

            //Json object to send to controller to check for vacancy
            var data = {
                floor: scope.person.floor,
                section: scope.person.section,
                seat: scope.person.offCubeNum
            };

            //can't send object via $http.get (?) stringigy json and cast to Office object in controller.
            var json = JSON.stringify(data);

            //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            //CHECK VACANCY service call
            //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            vacancyService.getData(json)
                .then(function (response) {
                if (response == false)
                    alert("cube/office occupied");
                else{

                    //+++++++++++++++++++++++++++++++++++++++++++
                    //UPDATE service call
                    //+++++++++++++++++++++++++++++++++++++++++++
                    //CONSTS
                    var CONSTFLOORPREFIX    = "f";
                    var CONSTSEAT           = "s";
                    var CONSTC              = "c"

                    var floor   = scope.person.floor;
                    var section = scope.person.section;

                    var offCube = scope.person.offCubeNum;
                    scope.person.oldSeatId = scope.person.seatId;

                    var newOfficeId = CONSTFLOORPREFIX + floor + CONSTSEAT;          //f3s 

                    //IF CUBE
                    if (scope.person.cbCube) {
                        var trimSection = section.trim();
                        newOfficeId += trimSection + CONSTC;                        //f3s313c
                        var trimOffCube = offCube.trim();
                        newOfficeId += trimOffCube;
                    }
                    else { 
                        newOfficeId += 0 + CONSTC + section;                                  //f3s0c
                    }



                    scope.person.seatId = newOfficeId;

                    //Json object to send to controller to check for vacancy
                    var data = {
                        Id: scope.person.Id,
                        seatId: scope.person.seatId,
                        oldSeatId: scope.person.oldSeatId,
                        empId: scope.person.empId,
                        lName: scope.person.lName,
                        fName: scope.person.fName,
                        refacName: scope.person.refacName,
                        deptId: scope.person.deptId,
                        divisionId: scope.person.divisionId,
                        jobDesc: scope.person.jobDesc,
                        seatTypeId: scope.person.seatTypeId,
                        officeCode: scope.person.officeCode,
                        phone: scope.person.phone,
                        floor: scope.person.floor,
                        section: scope.person.section,
                        seat: scope.person.seat,
                        vacant: scope.person.vacant
                    };


                    //call to update/move the employee 
                    //updateService.putData(scope.person).then(function () {
                    updateService.putData(data).then(function (response) {
                        if (response == false)
                            alert("Move Failed!");
                        else {
                            alert("Move Succeeded.");
                            //$window.location.reload();
                            $state.reload();
                            //$route.reload();
                            //scope.toggle = false;
                        }

                    });
                }//end else
            });
        }

        if (element[0].querySelector('text') != null){
            scope.htmlPopover = './HTML/popoverTemplate.html';
            element[0].setAttribute('uib-popover-template', "htmlPopover");
            element[0].setAttribute('popover-append-to-body', 'true');
            element[0].setAttribute('popover-trigger', "'click'");
            //element[0].setAttribute('popover-trigger', "'mouseenter'");
            element[0].setAttribute('popover-placement', 'right');
            element[0].removeAttribute('svg-floorplan-popover');
            $compile(element)(scope);
        }
    }
}
}]);

更新:2017 年 5 月 8 日
最初有一个额外的数据服务和一个指令,我们在这篇文章中遗漏了它,因为它可能被认为不是必不可少的信息,但最近添加了因为它可能是需要的。

SVG 加载指令:
angular.module('FFPA').directive('svgFloorplan', ['$compile', function ($compile) {
return {
    restrict: 'A',  //restrict attributes
    templateUrl: './SVG/HQ3RD-FLOOR3v10.svg',
    scope: {
        'dataset': '=svgFloorplan'
    },
    link: {
        pre: function (scope, element, attrs) {
            //filter groups based on a cube/office id
            var groups = element[0].querySelectorAll("g[id^='f3']");
            //groups.style("pointer-events", "all");
            scope.changeName = function (groupId) {
                if (scope.dataset[groupId] && scope.dataset[groupId].lastName.indexOf('changed') === -1) {
                    scope.dataset[groupId].lastName += ' changed';
                }
            }

            groups.forEach(function (group) {
                var groupId = group.getAttribute('id');
                if (groupId) {
                    //set vacancy colors on vacant cubes
                    scope.$watch("dataset", function () {
                        if (scope.dataset) {
                            if (typeof scope.dataset[groupId] !== "undefined") {

                                //vacant cubes and offices hover
                                if (scope.dataset[groupId].vacant == true) {
                                    //seat type id 1 = cube
                                    if (scope.dataset[groupId].seatTypeId == 1){
                                        d3.select(group).select("rect").style("fill", "#99ff33").style("opacity", 0.4)
                                            .style("pointer-events", "all")
                                            .on('mouseover', function () {
                                             d3.select(this).style('opacity', 0.9);
                                         })
                                        .on('mouseout', function () {
                                            d3.select(this).style('opacity', 0.4);
                                        })
                                    }
                                    //vacant office
                                    else {
                                        d3.select(group).select("path").style("stroke", "#ffffff").style("opacity", 1.0);
                                        d3.select(group).select("path").style("fill", "#99ff33").style("opacity", 0.4)
                                        .style("pointer-events", "all")
                                         .on('mouseover', function () {
                                             d3.select(this).style('opacity', 0.9);
                                         })
                                        .on('mouseout', function () {
                                            d3.select(this).style('opacity', 0.4);
                                        })
                                    }
                                }
                                else {                              //Occupied 
                                    //seat type id 1 = cube
                                    if (scope.dataset[groupId].seatTypeId == 1) {
                                        d3.select(group).select("rect").style("fill", "#30445d").style("opacity", 0.0)
                                         .style("pointer-events", "all")
                                         .on('mouseover', function () {
                                             d3.select(this).style('opacity', 1.0);
                                             d3.select(group).select('text').style("fill", "#FFFFFF");
                                         })
                                        .on('mouseout', function () {
                                            d3.select(this).style('opacity', 0.0);
                                            d3.select(group).select('text').style("fill", "#000000");
                                        })

                                        //TODO: cubes have rects and on the north side of the building wall, paths.
                                        d3.select(group).select("path").style("fill", "#30445d").style("opacity", 0.0)
                                            .style("pointer-events", "all")
                                            .on('mouseover', function () {
                                                d3.select(this).style('opacity', 1.0);
                                                d3.select(group).select('text').style("fill", "#FFFFFF");
                                            })
                                        .on('mouseout', function () {
                                            d3.select(this).style('opacity', 0.0);
                                            d3.select(group).select('text').style("fill", "#000000");
                                        })
                                    }
                                    //occupied office
                                    else {
                                        //d3.select(group).select("path").style("stroke", "#ffffff").style("opacity", 0.8);
                                        d3.select(group).select("path").style("fill", "#5A8CC9").style("opacity", 1.0)
                                         .style("pointer-events", "all")
                                         .on('mouseover', function () {
                                             //alert("office");
                                             d3.select(this).style("fill", "#2d4768").style('opacity', 1.0);
                                             d3.select(group).selectAll('text').style("fill", "#FFFFFF");
                                         })
                                        .on('mouseout', function () {
                                            d3.select(this).style("fill", "#5A8CC9").style('opacity', 1.0);
                                            d3.select(group).selectAll('text').style("fill", "#000000");
                                        })
                                    }
                                }//end occupied else
                            }
                        }
                    });
                     //UPDATE 8-MAY-2017->Implementation Question
                    scope.onDataUpdateInController = function (person, moreData) { };
                    var datasetBinding = "dataset['" + groupId + "']";
                    group.setAttribute('svg-floorplan-popover', datasetBinding);

                    //UPDATE 8-MAY-2017
                    //on-data-update corresponds to onDataUpdate item on svgFloorplanPopover's scope.
                    group.setAttribute('on-data-update', onDataUpdateInController);


                    $compile(group)(scope);
                }
            });
        }


    }
}
}]);

空缺服务(更新前检查):
angular.module('FFPA').service('vacancyService', function ($http) {
...
}

主要问题是:

我们如何让我们的应用程序在不重新加载页面的情况下使用更新的数据刷新我们的页面?

过去,我们曾经能够在 ASP.Net 网络表单的 UpdatePanels 中执行此操作。我认为它们是部分回发/AJAX 调用..

2017 年 8 月 2 日编辑

+++++++++++++++++++++++++++++++++++++

即使赏金是自动授予的,我们仍然没有这个问题的答案。没有任何实现上下文,给出的答案是没有用的。

任何人都可以扩展给出的答案,让我们了解如何解决这个问题?

谢谢

最佳答案

只需将您的数据添加到 $scope对象并在您的 View 中使用它,只要您更新或修改数据
例如:考虑你有一个函数来获取你正在对你的数据库进行休息调用的数据

$scope.getdata=function(){
$http.get(url).success(function(data)
{   $scope.data=data;
});

每当您修改数据时,只需点击指令/弹出窗口的关闭即可在您的情况下调用此函数

关于angularjs - 如何使用 AngularJS/Web API/Angular-ui-router 在指令中调用 $http.put 服务后更新页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43481363/

相关文章:

javascript - Angular js - 解析和运行()的执行顺序

AngularJS : broadcast event from directive

asp.net - 您可以在 .NET WebApi Route URI 中使用正则表达式进行 API 版本控制吗

javascript - AngularJS 指令到指令通信

html - 如果 bootstrap.min.css 链接两次会产生任何副作用

javascript - 如何从 AngularJs 中的本地存储中的键访问值?

c# - 为 POST API 请求发回多个响应

Breeze:EFContextProvider/Breeze Controller 和服务层

javascript - 使用angularjs获取函数返回值

html - 在使用 ng-bind-html 时,我应该如何使 html 元素出现在每个元素旁边?