Cómo actualizar la página después de llamar al servicio $ http.put en la directiva que utiliza AngularJS/API web/Angular-ui-enrutador
ng-bind-html angular 5 (3)
Por favor, prueba los siguientes pasos:
1. Crea un método en la directiva svgFloorplanPopover
y llámalo pasando los datos
En su directiva svgFloorplanPopover
, agregue el elementoDataUpdate en la declaración del alcance:
...
scope: {
''person'': ''=svgFloorplanPopover'',
onDataUpdate: ''&''
}
...
y cuando intenta volver a cargar el estado, en lugar de volver a cargar el estado o la página, llame al código siguiente. Esto es para crear un sistema de eventos que se active desde dentro de la directiva para que el controlador o la directiva principal sepan que los datos han cambiado y que la vista ahora puede actualizarse.
$scope.onDataUpdate({person: $scope.person, moreData: $scope.moreData});
2. Cree un método en svgFloorplan
para aceptar los datos pasados
Dado que usa un enfoque de directiva anidada, deberá usar el siguiente código en la directiva svgFloorplan
.
group.setAttribute(''svg-floorplan-popover'', datasetBinding);
group.setAttribute(''on-data-update'', onDataUpdateInController);
on-data-update
corresponde al elemento svgFloorplanPopover
el alcance de svgFloorplanPopover
.
Declare el método onDataUpdateInController
en el alcance de la directiva svgFloorplan
.
scope.onDataUpdateInController = function(person, moreData) {};
Las propiedades del objeto que pasa desde dentro de la directiva se presentan planas para la cantidad de parámetros.
Si necesita pasar esta información más adelante a su controlador donde se declara svgFloorplan
. Repita los dos pasos anteriores para la directiva svgFloorplan
.
Espero que este enfoque sea claro. No es diferente de lo que se explica en Directivas angulares , sección Creación de una directiva que envuelve otros elementos y código donde se agrega un botón de cerrar. Aquí está el enlace directo al código en plunkr .
Solo una pregunta: ¿Usará estas directivas por separado? Si no, puede intentar crear una directiva en lugar de hacerlas dos. Esto reducirá la complejidad.
Somos nuevos en AngularJS pero estamos trabajando en una aplicación AngularJS / Web API que actualiza un modelo de datos de un popover / directivo de AngularJS Bootstrap .
Hemos actualizado con éxito la base de datos de la directiva / popover, sin embargo, tenemos problemas para averiguar cómo actualizar los datos en la página con los datos actualizados sin volver a cargar la página.
Página principal 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>
La página principal recibe inicialmente datos de un servicio en el controlador angular:
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;
}, {});
});
});
Obtener servicio de datos:
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" };
}
);
}
});
El Servicio de actualización se llama desde la Directiva Popover.
Servicio de actualización:
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" };
}
);
}
});
Aquí hay un fragmento de nuestra directiva Popover donde ocurre la actualización y donde pensamos que podríamos actualizar el alcance y los datos de la página:
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();
}
});
Probamos un $ state.reload (); en la directiva popover justo después de updateService.putData (data), sin embargo esto causó -> Error: No se puede pasar al estado abstracto ''Objeto object'' ''error.
Aquí está la Directiva completa de 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);
}
}
}
}]);
ACTUALIZADO: 8-MAYO-2017 Originalmente, hay un servicio de datos adicional y una directiva que dejamos fuera de esta publicación, ya que puede considerarse información no esencial, aunque se haya agregado recientemente, ya que puede ser necesaria.
Directiva de carga 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);
}
});
}
}
}
}]);
Servicio de vacantes (consultar antes de la actualización):
angular.module(''FFPA'').service(''vacancyService'', function ($http) {
...
}
La pregunta principal es:
¿Cómo podemos hacer que nuestra aplicación actualice nuestra página con los datos actualizados sin volver a cargar la página?
Solíamos ser capaces de hacer esto en UpdatePanels en las formas web ASP.Net en el día. Creo que fueron postbacks parciales / llamadas AJAX ...
EDITADO 2-AGO-2017
+++++++++++++++++++++++++++++++++++
Aunque la recompensa se otorgó automáticamente, todavía no tenemos una respuesta a esta pregunta. Sin ningún contexto de implementación, las respuestas dadas no son útiles.
¿Alguien puede ampliar las respuestas dadas para darnos una idea de cómo se puede resolver este problema?
Gracias
Simplemente agregue sus datos en el objeto $scope
y úselos en su vista, cada vez que actualice o modifique los datos, por ejemplo: considere que tiene una función para obtener los datos en los que realiza el resto llame a su base de datos
$scope.getdata=function(){
$http.get(url).success(function(data)
{ $scope.data=data;
});
Cada vez que modifique sus datos solo llame a esta función en su caso al hacer clic en cerrar de directiva / emergente
Para actualizar su vista (no enlazar los datos recibidos) use las respuestas para las siguientes preguntas:
Uso del módulo ngRoute Cómo recargar o volver a procesar la página completa usando AngularJS
Uso del módulo de ui-enrutador Recarga del estado actual - actualización de datos
Con eso, le recomendaría que asigne los datos recibidos a su propiedad $ scope delimitada.
Agregaré un ejemplo completo después de que me proporcione un plnkr actualizado :)