Kendo UI Grid Persist state in AngularJS - angularjs

I have some problems loading the saved state of the grid in Angular.
This is the grids HTML:
<div id="grid" kendo-grid k-options="GridOptions" k-ng-delay="GridOptions"></div>
Later I start my Http call and the $scope.GridOptions are filled in and the grid works fine.
Then I save the state of my grid this way:
$scope.GridOptionsBackup = kendo.stringify($scope.GridOptions);
This works fine and when i print the output in the console. It looks like this:
{"dataSource":{"schema":{"data":"Data"},"transport":{},"serverSorting":true,"table":null,"fields":[{"encoded":true,"field":"WidgetName","title":"Name","template":"#: data.WidgetName#"},{"encoded":true,"field":"WidgetDescription","title":"Description","template":"#: data.WidgetDescription#"}]},"columns":[{"field":"WidgetName","title":"Name","template":"#: data.WidgetName#"},{"field":"WidgetDescription","title":"Description","template":"#: data.WidgetDescription#"}],"sortable":{"mode":"multiple","allowUnsort":true},"scrollable":true}
When i try to reload the grid with the saved state, i read the JSON, parse it and reassign it to $scope.GridOptions. But this don't work:
$scope.GridOptions = JSON.parse($scope.GridOptionsBackup);
Why is the grid not updated after this line of code?
I really appreciate any help you can provide!

I found the answer:
I had to give the kendo-grid a name:
<div kendo-grid="GridBram" k-options="GridOptions" k-ng-delay="GridOptions"></div>
In my Angular code, the name is automatically binded to a scope. There i can use the same (strange) get and setOptions methods that are used in jQuery. I also used a var to store the JSON.
This is my code:
var savedState = null;
$scope.saveO = function () {
savedState = kendo.stringify($scope.GridBram.getOptions());
console.log(test);
}
$scope.loadO = function () {
$scope.GridBram.setOptions(JSON.parse(savedState));
}
Like this, u can save and load the state of your grid in Angular!

Create 2 angular buttons
lt button kendo-button ng-click="save()" gt
Save State A
lt /button gt
lt button kendo-button ng-click="load()" gt
Load State A
lt /button gt
var savedState = null;
$scope.save = function () {
// alert('sav')
savedState = kendo.stringify($scope.GridMAS.getOptions());
}
$scope.load = function () {
//alert('lod')
$scope.GridMAS.setOptions(JSON.parse(savedState));
}
Worked for me

Related

angular file upload in ng-repeat with preview input bind

I'm working on an angular 1.6 based image upload with ng-repeat, note the input is not multi, but there are multiple ng-repeated inputs, I have the image preview working as well as adding lines / removing lines, the only thing that seems to not be working is if I remove an item the file inputs do not update (I have code that does properly update the previews). Here is what I am working with:
<div ng-repeat="item in data.items track by $index">
<input ng-model="item.fileinput" type="file" name="image_{{$index}}" id="image_{{$index}}" onchange="angular.element(this).scope().imageChoose(this)"/><i ng-click="removeEvent($index)" class="fa fa-trash fa-lg"></i>
<img ng-if="!item.thumb" class="preview-image-small" ng-src="/images/general/placeholder.jpg"</img>
<img ng-if="item.thumb" class="preview-image-small" ng-src="{{item.thumb}}"</img>
</div>
Then in my controller I handle the imageChoose as follows:
$scope.imageChoose = function (data) {
var id = data.id.split("_");
id = id[id.length-1];
var elem = document.getElementById(data.id);
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
reader.onload = function (e) {
$scope.$apply(function() {
$scope.data.data.items[id].thumb = e.target.result;
});
};
reader.readAsDataURL(elem.files[0]);
} else {
alert("This browser does not support FileReader.");
}
};
This properly sets the image previews and when I run a remove on a line they re-order correctly due to the ng-src of event.thumb. The problem is the actual file input does not bind or update, here is the code for removing a line:
$scope.removeEvent = function (index) {
$scope.data.items.splice(index, 1);
};
I'm hoping there is a relatively simple way to bind the input or handle the remove so that the inputs stay correct. Thanks in advance for any ideas.
Your removeEvent method is not working because of using track by $index together with ng-repeat. This is a known side effect. Try removing it/using different track by expressions.

How to get the value of selected row directly in HTML using ag-grid

i try to get the the value of number row selected, and print it in HTML using Angularjs, but no issue,
i have the count only when i clic in the grid column header.
The value of " selectedRowsCounter " is 0 in html, when i dosn't clic in the grid header
my code is like
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
};
$scope.gridOptions = {
rowData: null,
angularCompileRows: true,
onSelectionChanged: activeButtons,
}
there is a screenshot
i have open the same subject here
https://github.com/ceolter/ag-grid/issues/1023
i have added this line to activeButtons function and it work fine
$scope.gridOptions.api.refreshView();
i dont knew if there is a good solution, but that work for now
The problem seems to be with Angular being unaware of the $scope property change because ag-grid does not tell Angular that it has modified something in the $scope. Although it is difficult to tell if you don't show your view.
You can use onSelectionChanged the way you are using it to know how many rows have been selected, but you need to tell Angular that something has changed in its $scope by applying it.
Something like this:
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
window.setTimeout(function() {
this.$scope.$apply();
});
};
That way you can apply the $scope and the html view will reflect the changes.

cannot manipulate string with angular filter

I am an angular newbie and I study the book "Angular JS by example" and I try to create my own filter. (pp. 93-94).
In my controller this is the string I want to manipulate
procedure: "Assume a position, with feet together .\Slightly bend your knees, .\While in air, bring your legs out .\ As you are moving your legs outward"
and then I sanitise it
$scope.trustedHtml = $sce.trustAsHtml($scope.currentExercise.details.procedure);
Since this is an SPA , the filter is in the description-panel.ejs file, that is inside workout.ejs, that is inside index.ejs
description-panel.ejs has
<div class="panel-body" ng-bind-html ="trustedHtml | myLineBreakFilter"> </div>
workout.ejs has
<div id="video-panel" class="col-sm-3" ng-include="'description-panel.ejs'">
and index.ejs has
<script src="/javascripts/7MinWorkout/filters.js"></script>
filter.js has the filter
angular.module('7minWorkout').filter('myLineBreakFilter', function () {
return function (input) {
var str = input;
var br = "</br></br>";
var position = str.indexOf(".");
var output = [str.slice(0, position), br, str.slice(position)].join('');
return output ;
}
});
The filter should replace all the . with </br></br>.
This does not work and I get no text at all in my front-end. I get this error in the console
TypeError: str.slice is not a function at filters.js:22
Shouldn't basic js stuff like str.slice be supported out of the box? What am I missing?
Thanks
$sce.trustAsHtml() return you an object so slice will not work on it.You can pass that object to $sce.getTrustedHtml(object) to obtain the original value and then can apply slice on it.
angular.module('7minWorkout').filter('myLineBreakFilter', function ($sce) {
return function (input) {
var str = $sce.getTrustedHtml(input);
var br = "</br></br>";
var position = str.indexOf(".");
var output = [str.slice(0, position), br, str.slice(position)].join('');
return $sce.trustAsHtml(output) ;
}
});
Try this add this before the splice
str.toString();
str.splice(//pass parameters);

angular/firebase remove ng-repeat item and re-add

I have mapbox marker objects that are being stored in a Firebase array. They are being loaded as geojson markers on my map and I am also listing those objects in a container with a simple ng-repeat. My goal is to have a function where, if the particular marker is out of view, to remove that marker from the DOM. If the marker comes back into view, to include that back into the ng-repeated list.
Let's say my list is being displayed like this:
<div id="list-item-container">
<div class="list-item" title="{{marker.name}}" ng-repeat="marker in markers">{{marker.name}}</div>
</div>
In my controller, I'm trying to hide and show these list items based on them being in the map bounds like so:
var markers = L.mapbox.featureLayer()
.addTo(map);
markers.setGeoJSON($scope.driverMarkers);
var listingsFromMarker = function() {
var bounds = map.getBounds();
markers.eachLayer(function(marker) {
var inBounds = [], id = marker.toGeoJSON().$id;
var idElement = $('.list-item[title="'+marker.toGeoJSON().$id+'"]');
if (bounds.contains(marker.getLatLng())) {
HOW DO I GET THIS ITEM BACK IN MY LIST???
} else {
idElement.remove();
}
});
};
map.on('move', function() {
listingsFromMarker();
});
Can anyone steer me in the right direction on how to place this ng-repeated item back into the DOM?
Thank you.
This is not the Angular way to do things. Deleting the DOM element that was created by ng-repeat binding ruins the concept... why would you use Angular at all in this case.. In all cases DOM should be manipulated with the help of Angular directives which are controlled via model.
Thus you should store two arrays. One is the real data - all markers. Another contains only markers that are desired to be shown at this moment in the list.
It will look something like below
In view
<div class="list-item"
ng-repeat="marker in markersInView"
title="{{marker.name}}">{{marker.name}}</div>
In controller
var listingsFromMarker = function() {
var bounds = map.getBounds();
var inBounds = [];
markers.eachLayer(function(marker) {
if (bounds.contains(marker.getLatLng())) {
inBounds.push(marker);
}
});
$scope.markersInView = inBounds;
$scope.$apply();//as this happens on mapbox event it isn't in $digest cycle
//so need to tell Angular to update bindings
};
And of cause you need to initialize $scope.markersInView somewhere in the beginning. This code is not presented in OP so I don't invent it. I guess you will figure out how to filter markers on first show

Changing list-item css class using ng-class when mousing over Leaflet Map Markers

I've got a doozy of an ng-class problem.
So I have an app with a map/markers on the right and a list-item menu on the left with info about the markers (like Yelp or Foursquare).
With some of my beginner hacking, I got the hover events to sort of work:
But it's odd, the list-item (pink background on hover) only works when I mouseout of the marker. I'm trying to set it up so that when you mouse over the marker, the appropriate list-item's background changes and when you mouseout, it goes back to white. Most of the other ng-class examples/questions I read through seem to work quite differently (they're going for a different functionality).
Ok, to the code:
HTML
<div class="col-md-6" id="leftCol">
<div class="list-group" ng-controller="ShowsCtrl">
<div class="nav nav-stacked list-group-item" id="sidebar" ng-repeat="(key, show) in shows.features" ng-mouseover="menuMouse(show)" ng-mouseout="menuMouseout(show)" ng-class="{hover: $index == hoveritem}">
The key part there is the ng-class="{hover: $index == hoveritem}"
Now I'll show you where hoveritem comes from
Controller
$scope.hoveritem = {};
function pointMouseover(leafletEvent) {
var layer = leafletEvent.target;
//console.log(layer.feature.properties.id);
layer.setIcon(mouseoverMarker);
$scope.hoveritem = layer.feature.properties.id;
console.log($scope.hoveritem);
}
function pointMouseout(leafletEvent) {
var layer = leafletEvent.target;
layer.setIcon(defaultMarker);
}
$scope.menuMouse = function(show){
var layer = layers[show.properties.id];
//console.log(layer);
layer.setIcon(mouseoverMarker);
}
$scope.menuMouseout = function(show){
var layer = layers[show.properties.id];
layer.setIcon(defaultMarker);
}
// Get the countries geojson data from a JSON
$http.get('/json/shows.geojson').success(function (data, status) {
angular.extend($scope, {
geojson: {
data: data,
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.artist);
layer.setIcon(defaultMarker);
layer.on({
mouseover: pointMouseover,
mouseout: pointMouseout
});
layers[feature.properties.id] = layer;
//console.log(layers);
}
}
});
});
}]);
So mousing over a marker
(layer.on({
mouseover: pointMouseover,
mouseout: pointMouseout
});)
fires the appropriate functions which then changes the icon colors.
I connected the layer.feature.properties.id; to $scope.hoveritem so that my HTML can then use that as the index c. When you mouseover a marker, it then feeds the marker id through to $scope.hoveritem which then it turn goes into the $index part of the HTML, thus changing it's CSS class.
But something is awry. It only changes to the correct list item on mouseout instead of mouseover. Furthermore, I can't figure out to get it to return to the default white state. None of the list items should look active if the mouse is not on a marker.
Any ideas or hints on this would be very appreciated.
The reason for the delay in the mouseover effects was because of the angular $apply digest cycle. Angular basically wasn't aware of the changes to hoveritem. Wrapping it with $scope.$apply did the trick:
$scope.$apply(function () {
$scope.hoveritem = layer.feature.properties.id;
})

Resources