How to refresh page after calling $ http.put service in directive using AngularJS / Web API / Angular -ui-router

We are new to AngularJS, but are working on an AngularJS / Web API application that updates the data model from the AngularJS Bootstrap popover / directive,

We successfully updated the database from the / popover directive, however, you had problems figuring out how to update the data on the updated data page without reloading the page.

CSHTML Homepage:

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

The main page first receives data from the service in the 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; }, {}); }); }); 

Get data service:

  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" }; } ); } }); 

The update service is called from the Popover directive.

Update service:

  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" }; } ); } }); 

Here is a snippet from our Popover directive, where the update takes place, and where we thought we could update the scope and data for the page:

 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(); } }); 

We tried $ state.reload (); in the popover directive immediately after updateService.putData (data), however, this caused the error "Error: cannot switch to abstract state" [object Object].

Here is the complete Popover Directive:

 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); } } } }]); 

UPDATED: MAY 8, 2017 Initially, there is one additional data service and directive that we left outside this post, as it may be considered non-essential information, but recently added, as it may be needed.


SVG Download Directive:

 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 scope. group.setAttribute('on-data-update', onDataUpdateInController); $compile(group)(scope); } }); } } } }]); 

Vacancy Service (check before upgrade):

 angular.module('FFPA').service('vacancyService', function ($http) { ... } 

The main question:

How can we refresh our page with updated data without reloading the page?

We used to do this in UpdatePanels in ASP.Net web formats the same day. I think they were partial AJAX callbacks / calls.

EDITED 2-AUG-2017

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

Despite the fact that the award was automatically awarded, we still do not have an answer to this question. Without any implementation context, the answers are not useful.

Can someone expand their answers to give us an idea of ​​how this problem can be solved?

thanks

+8
angularjs asp.net-web-api angularjs-scope angularjs-directive angular-bootstrap
source share
3 answers

Just add your data to the $scope object and use it in your view, whenever you update or change the data just for example: think that you have a function to get the data in which you are resting on your db

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

Whenever you change your data, just call this function in your case when you press the close directive / popup

+3
source

Use the answers to the following questions to update the view (do not link the data):

Using the ngRoute module How to reload or redisplay an entire page using AngularJS

Using the ui-router module Rebooting the current state - updating data

With this, I would recommend that you assign the received data to your limited $ scope property.

I will add a complete example after you provide the updated plnkr file :)

+1
source

Try the following:

1. Create a method in the svgFloorplanPopover directive and call it by passing data

In your svgFloorplanPopover directive svgFloorplanPopover add the onDataUpdate element to the onDataUpdate scope:

 ... scope: { 'person': '=svgFloorplanPopover', onDataUpdate: '&' } ... 

and where you are trying to reload the state, instead of reloading the state or page, call the code below. This is done to create an event system that runs from the directive to let the controller or parent directive know that the data has been changed, and now the view can be updated.

 $scope.onDataUpdate({person: $scope.person, moreData: $scope.moreData}); 

2. Create a method in svgFloorplan to accept the transferred data

Since you are using a nested directive approach, you need to use the code below in the svgFloorplan directive.

 group.setAttribute('svg-floorplan-popover', datasetBinding); group.setAttribute('on-data-update', onDataUpdateInController); 

on-data-update corresponds to the onDataUpdate element in the svgFloorplanPopover .

Declare the onDataUpdateInController method in the scope of the svgFloorplan directive.

 scope.onDataUpdateInController = function(person, moreData) {}; 

The properties of the object that you pass from the directive are laid out in accordance with the number of parameters.

If you need to transfer this data further to your controller, where svgFloorplan declared. Repeat the above two steps for the svgFloorplan directive.

I hope this approach is clear. This is no different from what is explained in the Angular Directives , section Creating a Directive, which wraps other elements and code where a close button is added. Here is a direct link to code in plunkr .

Just a question: Are you going to use these directives separately from each other? If not, you can try to create one directive instead of making them two. This will reduce complexity.

+1
source

All Articles