我们是AngularJS的新手,但正在开发一个AngularJS/Web API应用程序,该应用程序从AngularJS引导弹出/指令更新数据模型。
我们已经成功地从指令/popover更新了数据库,但是我们很难弄清楚如何在不重新加载页面的情况下使用更新的数据刷新页面上的数据。
主页CSHTML:
<div ng-app="FFPA" ng-controller="myCtrl">
<div svg-floorplan="dataset"></div>
</div>
Popover 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>
主页最初从角度控制器中的服务获取数据:
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();在updateS之后的popover指令中ervice.putData(数据),但是这导致-
以下是完整的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网络表单的更新面板中做到这一点。我认为他们是部分回发/AJAX调用...
编辑日期:2017年8月2日
即使赏金是自动授予的,我们仍然没有这个问题的答案。如果没有任何实现上下文,给出的答案是无用的。
有没有人能在给出的答案基础上进一步阐述,让我们了解如何解决这个问题?
谢谢
请尝试以下步骤:
在您的svgFloorplan Popover
指令中,在范围声明中添加onDataUpdate
项:
...
scope: {
'person': '=svgFloorplanPopover',
onDataUpdate: '&'
}
...
如果您试图重新加载状态,而不是重新加载状态或页面,请调用下面的代码。这是为了创建一个事件系统,该系统从指令内激发,以让控制器或父指令知道数据已更改,并且视图现在可以更新。
$scope.onDataUpdate({person: $scope.person, moreData: $scope.moreData});
由于您使用的是嵌套指令方法,因此需要在svgFloorplan
指令中使用以下代码。
group.setAttribute('svg-floorplan-popover', datasetBinding);
group.setAttribute('on-data-update', onDataUpdateInController);
数据更新上的对应于
svgFloorplanPopover
范围上的onDataUpdate
项。
在
svgFloorplan
指令的范围内声明OnDataUpdateInControl
方法。
scope.onDataUpdateInController = function(person, moreData) {};
从指令中传递的对象特性将按参数数平铺。
如果需要将此数据进一步传递到控制器,其中声明了
svgFloorplan
。对svgFloorplan
指令重复上述两个步骤。
我希望这一方针是明确的。这与Angular指令中的解释没有什么不同,创建一个指令部分在添加关闭按钮的地方封装了其他元素和代码。下面是指向plunkr中代码的直接链接。
只是一个问题:您是否要分别使用这些指令?如果没有,您可以尝试创建一个指令,而不是将它们设为两个。这将降低复杂性。
要刷新视图(不绑定收到的数据),请使用以下问题的答案:
使用ngRoute模块如何使用AngularJS重新加载或重新呈现整个页面
使用ui路由器模块重新加载当前状态-刷新数据
因此,我建议您将接收到的数据分配给绑定的$scope属性。
在您提供更新的plnkr之后,我将添加一个完整的示例:)
只要把你的数据添加到<代码> $Simule对象,并在视图中使用它,每当你更新或修改数据时,例如:考虑到你有一个函数来获取你正在向数据库进行Hibernate调用的数据。
$scope.getdata=function(){
$http.get(url).success(function(data)
{ $scope.data=data;
});
每当您修改数据时,只要在您的情况下单击关闭指令/弹出窗口即可调用此函数
问题内容: 我正在使用Express,它从静态目录加载AngularJS。通常,我会要求Express为其提供我和所有正确的Angular文件等。在我的Angular应用中,我有这些路由设置,它们替换了内容: 在我的主页上,我有到的链接,该链接将成功加载模板并将我定向到或指定的任何ID。问题是当我尝试将浏览器定向到页面或刷新页面时,请求将发送到Express / Node服务器,该服务器返回。 我
问题内容: 我正在使用AngularJS,并试图在显示该标签的内容时向菜单添加“当前”类。这是我到目前为止所拥有的,并且在加载页面时可以正常工作: HTML: JS: 当页面网址为或时,这会将“当前”类添加到正确的标记中 问题是,如果我单击第二个选项卡,则不会将类添加到其中。我想我需要某种方法来使指令内部的代码在URL更改时重新运行。有什么办法吗? 问题答案: 在评论中使用来自kfis代码,现在可
问题内容: 我想创建一个使用asp.net mvc webapi作为后端和客户端路由(没有cshtml)的SPA angularjs应用程序中的身份验证和授权的示例。以下只是可用于设置完整示例的函数示例。但是我不能一概而论。任何帮助表示赞赏。 问题: 最佳实践是什么:基于Cookie或令牌? 如何创建有角度的承载令牌以对每个请求进行授权? 验证API函数? 如何在客户端上保留登录的登录用户? 示例
问题内容: 我已经用AngularJS编写了一个服务,但是我无法使其与角度种子处理方式一起使用。 控制器代码如下: 请注意,注释掉的部分工作正常,但我想像(推荐的)第二种方式来处理它。 我得到的错误是照片是未定义的,所以我的猜测是我传递(注入)它的方法是错误的,但是我找不到正确的方法 问题答案: 您需要定义服务: 一些参考: http://docs.angularjs.org/api/angula
我使用的是带有一个简单的路由器插座元件的Angular2 RC5和Angular2/router。我有一个可观察的,在视图中运行良好,但当你刷新页面时(F5或CTRL-F5),它就不起作用了。我在Chrome(最新版本)和IE11(可能还有其他浏览器)中都有这个功能。目前我有一个变通方法,但我不明白为什么我的更改没有自动反映在视图中。 该项目相当大,因此请尽量减少: 在MyService.ts 在
问题内容: 我有一个正在使用的应用程序,每当刷新页面时都会遇到问题。我正在使用嵌套视图(命名视图)来构建应用程序。每当我刷新页面时,都不会重新加载当前状态,只会使页面空白。 页面加载等于 我正在通过文件并通过状态循环从文件中读取导航。这就是我可以显示的内容: 对于嵌套json对象中的每个项目,将执行此代码。如果还有其他有用的方法,请告诉我。 问题答案: 有一个问题:AngularJS-UI-rou