Angular ui-grid doesn't update view after data arrived from server - javascript

Maybe this question was asked before, but i tried the solutions i saw in other posts such as disabling the fast watch, but nothing seems to work...
I have a grid using Angular ui-grid in my web page and the behavior i'm seeking for is that after click on a button the data must be updated. The issue is i can see that gridOptions.data is updated, the columnDefs too, even the length but view doesn't update, also the displaying becomes a bit messy and i have to scroll to get it right.
Here's my code
Controller :
(function(app) {
'use strict';
app.controller('Ctrl', Ctrl);
function Ctrl($scope, $routeSegment, $log, $filter) {
$log.debug('Controller - init()');
// Set ViewModel Object - will be exported in View
var viewModel = this;
viewModel.gridOptionsData = [];
viewModel.gridOptions = {};
viewModel.gridOptions.paginationPageSizes = [25, 50, 75];
viewModel.gridOptions.paginationPageSize = 25;
viewModel.gridOptions.data = [];
viewModel.gridOptions.rowIdentity = function(row) {
return row.id;
};
viewModel.gridOptions.getRowIdentity = function(row) {
return row.id;
};
$scope.showgrid = false;
$scope.filterText;
viewModel.refreshData = function() {
viewModel.gridOptions.data = $filter('filter')(viewModel.gridOptionsData, $scope.filterText, undefined);
};
$scope.$watch('dataStructure', function(data) {
if (angular.isDefined(data) && !angular.equals(data, [])) {
var struct = [];
for (var key in data[0]) {
if (angular.equals(key, 'id')) {
struct.push({
field: key,
visible : false
});
} else {
struct.push({
field: key,
});
}
}
viewModel.gridOptionsData = data;
viewModel.gridOptions.data = data;
viewModel.gridOptions.columnDefs = struct;
$scope.showgrid = true;
}
});
}
}(angular.module('app')));
View :
<div class="gridStyle" ui-grid="pageViewModel.gridOptions" ui-grid-pagination ></div>
<input type="text" ng-model="$parent.filterText" ng-change="pageViewModel.refreshData()" placeholder="Search / Filter" />
Appreciate your help

Related

AngularJS select items not resetting to first / default value

I'm at my wits end! In angular I've got a controller and a view.
There are 2 dropdowns on the page which need to reset to default once the restart button has been clicked.
I can set the value of the boxes as they render by pushing a "select" option into the collection inside the controller. However, when the reset button is pressed, which runs the init() method again, the dropdowns should be set back to the first value. This doesn't occur, the values for $scope.selectedYear and $scope.selectedReport remain as they did before the reset button was pressed.
This is the full code for the controller
function TreeReportsCHLController($scope, $q, $routeParams, reportsDashboardResource, navigationService, notificationsService, dialogService, entriesManageDashboardResource, $timeout) {
// Methods
var generalError = function () {
notificationsService.error("Ooops", "There was an error fetching the data");
$scope.actionInProgress = false;
}
// Scope
$scope.selectedYear = "";
$scope.init = function () {
$scope.hasCompleted = false;
$scope.actionInProgress = false;
$scope.yearSelected = false;
$scope.reportTypes = ["Choose", "Entered", "ShortListed", "Winner", "Recieved"];
$scope.selectedReport = "";
$scope.entryYears = new Array();
$scope.entryYears.push("Choose a Year");
entriesManageDashboardResource.getEntryYears().then(function (response) {
angular.forEach(response, function (value, key) {
$scope.entryYears.push(value);
});
});
$scope.selectedYear = $scope.entryYears[0];
$scope.selectedReport = $scope.reportTypes[0];
};
$scope.yearHasSelected = function(selectedYear) {
$scope.yearSelected = true;
$scope.selectedYear = selectedYear;
};
$scope.generateFile = function (selectedReport) {
$scope.actionInProgress = true;
var reportDetail = {
entryYear: $scope.selectedYear,
chosenEntryStatus: selectedReport
};
reportsDashboardResource.generateEntriesReportDownloadLink(reportDetail).then(function (response) {
if (response.Successful) {
$scope.hasCompleted = true;
} else {
notificationsService.error("Ooops", response.ErrorMessage);
}
$scope.actionInProgress = false;
}, generalError);
};
$scope.restart = function () {
$scope.init();
}
// Initialise Page
$scope.init();
}
angular.module("umbraco").controller("ReportsDashboardController", TreeReportsCHLController)
this is the code with the dropdowns in it;
<table>
<tr>
<td>Get a report for year: {{selectedYear}}</td>
<td><select ng-model="selectedYear" ng-change="yearHasSelected(selectedYear)" ng-options="year for year in entryYears" no-dirty-check></select></td>
</tr>
<tr ng-show="!hasCompleted && yearSelected">
<td>
Get Report Type:
</td>
<td>
<select ng-model="selectedReport" ng-change="generateFile(selectedReport)" ng-options="status for status in reportTypes" no-dirty-check ng-disabled="actionInProgress"></select>
</td>
</tr>
</table>
I've also done a further test where I simply set $scope.selectedYear to $scope.entryYears[0] within the reset method. When I console.log $scope.selectedYear here, the value confirms it has been changed, but strangely where I've outputted the $scope.selectedYear / {{selectedYear}} to the page for testing, this does not update. It's almost as though the binding between the controller and the view isn't occuring.
Any help?
Thank-you.
Here's a working plunk that is somewhat stripped down since I didn't have access to of the services that your are injecting into your controller. The changes I made in the controller are:
First,
$scope.entryYears = new Array();
becomes
$scope.entryYears = [];
as this is the preferred way to declare an array in js.
Second, I removed $scope.apply() that was wrapping
$scope.selectedYear = $scope.entryYears[0];
$scope.selectedReport = $scope.reportTypes[0];
as this was causing infinite digest cycles.

ng-change is not firing when changing value from service

I need to reflect some changes to controller B (inside some event) when I make change at controller A. For that I am using a service.
When I am changing service value from FirstCtrl, ng-change is not firing at SecondCtrl. Is there anything I have missed or need to change?
Please note that I am using angular 1.5.6. and don't want to use watch or even scope.
Below is my code.
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
return {
FirstName: ''
};
});
myApp.controller('FirstCtrl', ['Data',
function(Data) {
var self = this;
debugger
self.changeM = function() {
debugger
Data.FirstName = self.FirstName;
};
}
]);
myApp.controller('SecondCtrl', ['Data',
function(Data) {
var self = this;
self.FirstName = Data;
self.changeM = function() {
alert(1);
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="FirstCtrl as c">
<input type="text" ng-model="c.FirstName" data-ng-change="c.changeM()">
<br>Input is : <strong>{{c.FirstName}}</strong>
<div ng-controller="SecondCtrl as c1">
Input should also be here: {{c1.FirstName}}
<input type="text" ng-model="c1.FirstName" data-ng-change="c1.changeM()">
</div>
</div>
<hr>
</div>
As you dont want to use $scope trying modifying the code in order to use $emit and $on feature in angular js to communicate between two controllers. You can refer this link.
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
return {
FirstName: ''
};
});
myApp.controller('FirstCtrl', ['Data',
function(Data) {
var self = this;
debugger
self.changeM = function() {
debugger
//Data.FirstName = self.FirstName;
Data.$on('emitData',function(event,args){
Data.FirstName=args.message
document.write(Data.FirstName)
})
};
}
]);
myApp.controller('SecondCtrl', ['Data',
function(Data) {
var self = this;
self.FirstName = Data;
self.changeM = function() {
Data.$emit('emitData',{
message:Data.FirstName
})
};
}
]);
The only way then is to directly copy the reference of the data object within the controller. Note that you don't need ng-change to update the value then.
If you want something else, either wrap the FirstName in a sub object of Data and do the same i did :
Data = {foo:'FirstName'};
Or use $watch since it's the whole purpose of that function.
Here is a working code with copying the Data object in the controller.
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
return {
FirstName: ''
};
});
myApp.controller('FirstCtrl', ['Data',
function(Data) {
var self = this;
self.Data=Data;
debugger
self.changeM = function() {
debugger
};
}
]);
myApp.controller('SecondCtrl', ['Data',
function(Data) {
var self = this;
self.Data = Data;
self.changeM = function() {
alert(1);
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="FirstCtrl as c">
<input type="text" ng-model="c.Data.FirstName" data-ng-change="c.changeM()">
<br>Input is : <strong>{{c.Data.FirstName}}</strong>
<div ng-controller="SecondCtrl as c1">
Input should also be here: {{c1.Data.FirstName}}
<input type="text" ng-model="c1.Data.FirstName" data-ng-change="c1.changeM()">
</div>
</div>
<hr>
</div>
The only way I know to solve the problem is using watch, unfortunately. (I am new to angular.)
From the ngChange document (https://docs.angularjs.org/api/ng/directive/ngChange):
The ngChange expression is only evaluated when a change in the input value causes a new value to be committed to the model.
It will not be evaluated:
if the value returned from the $parsers transformation pipeline has not changed
if the input has continued to be invalid since the model will stay null
**if the model is changed programmatically and not by a change to the input value**

Getting value from JSON object with Angular

I've been trying to learn AngularJS recently, and hit a bump in the road with Localstorage i spend so many hours trying to make it save locally, I think that it's working as it should now, but now i would like to print out the data saved local from the JSON array, how can i go about that?
EDIT:
A bit of clarification, What im trying to achieve is getting the information i save in the localstorage out onto the website as a string, so it's readable. hope i'ts more understandable. Thanks in advance
My view.
<ion-list>
<div >
<ion-item ng-controller='ModalEditCtrl' ng-click="openModal()">
<div class="thumbnail" style="border:1px black solid">
</div>
<div ng-controller="createPerson" class="contactinfo" >
<li ng-repeat="contact in contactdetail.contactinfo"> {{contact.name}} </li>
</div>
</ion-item>
</div>
<div ng-controller="ModalAddCtrl">
<button type="button" ng-click="openModal()">+++</button>
</div>
</ion-list>
My controller
app.controller('createPerson', function ($scope) {
var id = id_counter = 1;
$scope.editorEnabled = false;
$scope.disableEditor = function() {
$scope.editorEnabled = false;
};
$scope.enableEditor = function() {
$scope.editorEnabled = true;
};
$scope.contactinfo = [
{name: 'test', phone: 1231, email: 'asd#asd.com'}
];
$scope.saveData = function () {
id_counter += 1;
$scope.editorEnabled = false;
$scope.contactinfo.push({
name: $scope.contactName,
phone: $scope.contactPhone,
email: $scope.contactEmail,
sort_id: id_counter
});
//$scope.todoText = ''; //clear the input after adding
localStorage.setItem('contactinfo', JSON.stringify($scope.contactinfo));
// localStorage.setItem("contacts", JSON.stringify(contacts));
}
$scope.loadData = function () {
var contacts = localStorage.getItem("contactinfo");
var contactdetail = JSON.parse(contacts); //
console.log(contactdetail);
}
$scope.clearData = function () {
window.localStorage.clear();
}
});
Your question is not very clear, I dont think you will be able to get much help unless you clean it up a little.
To print out the data (for debugging, usually) you could just add {{contactinfo|json}} somewhere in your html.
To actually display the data for use on the webpage the following should work for you.
<div ng-repeat="contact in contactinfo track by $index">
<div>Name: {{contact.name}}</div>
<div>Phone: {{contact.phone}}</div>
<div>Email: {{contact.email}}</div>
</div>
I think that some of that logic might be better split into a factory, too. Something like this maybe...?
var contactFactory = angular.module('contactFactory', []);
contactFactory.factory('contactInfo', ['$window', function ($window) {
var id = id_counter = 1;
var contacts = [];
function addContact(name, phone, email) {
id_counter += 1;
contacts.push({
name: name,
phone: phone,
email: email,
sort_id: id_counter
});
saveData();
}
function saveData(contactInfo) {
$window.localStorage.setItem('contactinfo', angular.fromJson(contacts));
}
function loadData() {
contacts = angular.toJson($window.localStorage.getItem('contactinfo'));
return contacts;
}
function clearData() {
$window.localStorage.removeItem('contactinfo');
}
return {
addContact: addContact,
saveData: saveData,
loadData: loadData,
clearData: clearData
};
}]);
var app = angular.module('yourAppName', ['contactFactory']);
app.controller('createPerson', ['$scope', 'contactInfo', function ($scope, contactInfo) {
$scope.editorEnabled = false;
$scope.disableEditor = function() {
$scope.editorEnabled = false;
};
$scope.enableEditor = function() {
$scope.editorEnabled = true;
};
$scope.contactinfo = [
{name: 'test', phone: 1231, email: 'asd#asd.com'}
];
$scope.saveData = function () {
contactInfo.addContact($scope.contactName, $scope.contactPhone, $scope.contactEmail);
$scope.editorEnabled = false;
}
$scope.loadData = contactInfo.loadData;
$scope.clearData = contactInfo.clearData;
}]);
Angular has wrapper for window, which should be used inside your code. There is also ngStorage module or many available solutions which are dealing with browser storage in Angular way. Moreover Angular has functions like angular.toJson() and angular.fromJson(). If e.g. jsonObj is JSON array then var obj = angular.fromJson(jsonObj) gives you JavaScript array. If jsonObj has array property inside then you should go with: var jsArray = angular.fromJson(jsonObj).array.

Why can't I do a $scope update within a jQuery scope?

I'm using typeahead to get some suggestions on an input text, this is inside a div controlled by an Angular controller.
The code for the suggestion tasks works with a jQuery plugin, so when I select, something I'm trying to assign a value to $scope, however this is NEVER happening.
I already tried getting the scope of the element with var scope = angular.element($("#providersSearchInput").scope() and then assign it as suggested here but it didn't work.
This is what I'm trying:
<div class="modal-body" ng-controller="ProvidersController" ng-init="orderReviewTab = 'observations'">
<input type="text" id="providersSearchInput" data-provide="typeahead" class="form-control input-md" placeholder="Buscar proovedores">
{{currentProvider}}
</div>
The controller looks like this:
tv3App.controller('ProvidersController', function($scope, $rootScope, $http, $timeout) {
var resultsCache = [];
$("#providersSearchInput").typeahead({
source: function (query, process) {
return $.get("/search/providers/?query=" + query, function (results) {
resultsCache = results;
return process(results);
},'json');
},
matcher: function (item) {
var name = item.name.toLowerCase();
var email = item.email.toLowerCase();
var contact_name = item.contact_name.toLowerCase();
//console.log(name);
var q = this.query.toLowerCase();
return (name.indexOf(q) != -1 || email.indexOf(q) != -1 || contact_name.indexOf(q) != -1);
},
scrollHeight: 20,
highlighter: function (itemName) {
var selected = _.find(resultsCache,{name:itemName});
var div = $('<div></div>');
var name = $('<span ></span>').html('<strong style="font-weight:bold">Empresa: </strong> ' + selected.name);
var contact = $('<span ></span>').html(' <strong style="font-weight:bold">Contacto: </strong> ' + selected.contact_name);
var email = $('<span ></span>').html(' <strong style="font-weight:bold">e-mail:</strong> ' + selected.email);
return $(div).append(name).append(contact).append(email).html();
},
minLength: 3,
items: 15,
afterSelect: function (item) {
console.log(item);
$scope.$emit('providerSelected',item);
}
});
$scope.$on('providerSelected', function (event,provider) {
console.log(provider);
$scope.currentProvider = provider;
$scope.$apply();
});
});
Edit
I tried this to check any changes:
$scope.$watch('currentProvider',function (newValue,oldValue) {
console.log(oldValue);
console.log(newValue);
});
So when selecting something it actually triggers and $scope.currentProvider seems to be updated but its never getting rendered at view ...
get https://angular-ui.github.io/bootstrap/
once you do, in your code make sure
angular.module('myModule', ['ui.bootstrap']);
and for typeahead have
<input type="text" ng-model="currentProvider" typeahead="provider for provider in getProviders($viewValue) | limitTo:8" class="form-control">
In your controller make sure you have
$scope.getProviders = function(val){
return $http.get('/search/providers/?query=' + val).then(function(response){
return response.data;
})
}
This should do the trick although I haven't tested

alternative method instead $watch in angularjs

I have a scope variable, when it returns true, i need to trigger some events or do something. I my case, the every first time, the scope variable returns undefined and later it returns true. In this case i used $watch method to get the expected funcionality. Is there any alternative approach to do the same instead using $watch ?
scope.$watch () ->
scope.initiateChild
, (value) ->
if value is true
$timeout ->
scope.buildOnboarding()
, 1000
You can try using AngularJS $on(), $emit() and $broadcast().
Here is an example: http://www.binaryintellect.net/articles/5d8be0b6-e294-457e-82b0-ba7cc10cae0e.aspx
You can use JavaScript getters and setters without any expense of using $watch.
Write code in the setter to do what you want when angular changes the your model's value you are using in scope. It gets null or an a State object as user types. Useful for working with type ahead text boxes that have dependencies on each other. Like list of counties after typing state without user selecting anything.
Here is some pseudo style code to get the idea.
<input ng-model="searchStuff.stateSearchText" />
<div>{{searchStuff.stateObject.counties.length}}</div>
<div>{{searchStuff.stateObject.population}}</div>
$scope.searchStuff=new function(){var me=this;};
$scope.searchStuff.stateObject = null;
$scope.searchStuff.getStateObjectFromSearchText = function(search){
// get set object from search then
return stateObject;
};
$scope.searchStuff._stateSearchText= "";
Object.defineProperty($scope.searchStuff, 'stateSearchText', {
get: function () {
return me._stateSearchText;
},
set: function (value) {
me,_stateSearchText = value;
me.stateObject = getStateObjectFromSearchText (value);
}
});
See this fiddle: http://jsfiddle.net/simpulton/XqDxG/
Also watch the following video: Communicating Between Controllers
A sample example is given below
Html:
<div ng-controller="ControllerZero">
<input ng-model="message" >
<button ng-click="handleClick(message);">LOG</button>
</div>
<div ng-controller="ControllerOne">
<input ng-model="message" >
</div>
<div ng-controller="ControllerTwo">
<input ng-model="message" >
</div>
javascript:
var myModule = angular.module('myModule', []);
myModule.factory('mySharedService', function($rootScope) {
var sharedService = {};
sharedService.message = '';
sharedService.prepForBroadcast = function(msg) {
this.message = msg;
this.broadcastItem();
};
sharedService.broadcastItem = function() {
$rootScope.$broadcast('handleBroadcast');
};
return sharedService;
});
function ControllerZero($scope, sharedService) {
$scope.handleClick = function(msg) {
sharedService.prepForBroadcast(msg);
};
$scope.$on('handleBroadcast', function() {
$scope.message = sharedService.message;
});
}
function ControllerOne($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'ONE: ' + sharedService.message;
});
}
function ControllerTwo($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'TWO: ' + sharedService.message;
});
}
ControllerZero.$inject = ['$scope', 'mySharedService'];
ControllerOne.$inject = ['$scope', 'mySharedService'];
ControllerTwo.$inject = ['$scope', 'mySharedService'];

Categories

Resources