My objective is to have a map to which I can add markers/polygons/... These elements will be saved into an Object for saving. The drawn elements can later be edited/deleted or added to.
I have successfully managed to create/edit/delete them, but when I init my map with the saved objects they can't be edited again.
Working fiddle : http://jsfiddle.net/4fq6m3dc/1/
My code :
leafletData.getMap().then(function (map) {
var drawnItems = $scope.controls.edit.featureGroup;
// Init the map with the saved elements
for (var i = 0; i < $scope.savedItems.length; i++) {
layer = new L.GeoJSON($scope.savedItems[i].geoJSON);
drawnItems.addLayer(layer);
}
map.on('draw:created', function (e) {
var layer = e.layer;
drawnItems.addLayer(layer);
$scope.savedItems.push({
id: layer._leaflet_id,
geoJSON: layer.toGeoJSON()
});
});
map.on('draw:edited', function (e) {
var layers = e.layers;
layers.eachLayer(function (layer) {
for (var i = 0; i < $scope.savedItems.length; i++) {
if ($scope.savedItems[i].id == layer._leaflet_id) {
$scope.savedItems[i].geoJSON = layer.toGeoJSON();
}
}
});
});
map.on('draw:deleted', function (e) {
var layers = e.layers;
layers.eachLayer(function (layer) {
for (var i = 0; i < $scope.savedItems.length; i++) {
if ($scope.savedItems[i].id == layer._leaflet_id) {
$scope.savedItems.splice(i, 1);
}
}
});
});
});
I modified your code and it seems that I have fixed the bugs for you. Here is my code.
<!DOCTYPE html>
<html ng-app="demoapp">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="http://tombatossals.github.io/angular-leaflet-directive/bower_components/angular/angular.min.js"></script>
<script src="http://tombatossals.github.io/angular-leaflet-directive/bower_components/leaflet/dist/leaflet.js"></script>
<script src="http://tombatossals.github.io/angular-leaflet-directive/dist/angular-leaflet-directive.min.js"></script>
<script src="http://tombatossals.github.io/angular-leaflet-directive/bower_components/leaflet.draw/dist/leaflet.draw.js"></script>
<link rel="stylesheet" href="http://tombatossals.github.io/angular-leaflet-directive/bower_components/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="http://tombatossals.github.io/angular-leaflet-directive/bower_components/leaflet.draw/dist/leaflet.draw.css" />
<script>
var app = angular.module("demoapp", ["leaflet-directive"]);
app.controller("ControlsDrawController", ["$scope", "leafletData", function($scope, leafletData) {
$scope.savedItems = [{
"id": 721,
"geoJSON": {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-0.626220703125,
48.1367666796927
]
}
}
}, {
"id": 724,
"geoJSON": {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-0.274658203125,
49.13859653703879
]
}
}
}, {
"id": 725,
"geoJSON": {"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-18.10546875,53.38332836757156],[-10.107421874999998,55.92458580482951],[-3.33984375,53.9560855309879],[-10.634765625,47.635783590864854],[-17.2265625,45.767522962149904],[-18.10546875,53.38332836757156]]]}}
}];
var drawnItems = new L.FeatureGroup();
for (var i = 0; i < $scope.savedItems.length; i++) {
L.geoJson($scope.savedItems[i].geoJSON, {
style: function(feature) {
return {
color: '#bada55'
};
},
onEachFeature: function (feature, layer) {
drawnItems.addLayer(layer);
}
});
}
angular.extend($scope, {
london: {
lat: 51.505,
lng: -0.09,
zoom: 4
},
controls: {
draw: {},
edit: {
featureGroup: drawnItems
}
}
});
leafletData.getMap().then(function(map) {
var drawnItems = $scope.controls.edit.featureGroup;
// Init the map with the saved elements
var printLayers = function () {
console.log("After: ");
map.eachLayer(function(layer) {
console.log(layer);
});
};
drawnItems.addTo(map);
printLayers();
map.on('draw:created', function(e) {
var layer = e.layer;
drawnItems.addLayer(layer);
console.log(JSON.stringify(layer.toGeoJSON()));
$scope.savedItems.push({
id: layer._leaflet_id,
geoJSON: layer.toGeoJSON()
});
});
map.on('draw:edited', function(e) {
var layers = e.layers;
layers.eachLayer(function(layer) {
for (var i = 0; i < $scope.savedItems.length; i++) {
if ($scope.savedItems[i].id == layer._leaflet_id) {
$scope.savedItems[i].geoJSON = layer.toGeoJSON();
}
}
});
});
map.on('draw:deleted', function(e) {
var layers = e.layers;
layers.eachLayer(function(layer) {
for (var i = 0; i < $scope.savedItems.length; i++) {
if ($scope.savedItems[i].id == layer._leaflet_id) {
$scope.savedItems.splice(i, 1);
}
}
});
});
});
}]);
</script>
<style>
input {
width: 120px;
margin-right: 10px;
}
</style>
</head>
<body ng-controller="ControlsDrawController">
<leaflet center="london" controls="controls" width="100%" height="400"></leaflet>
<h1>Draw control example</h1>
<p>Draw a shape and a geoJSON data structure will be shown on the console.log.</p>
</body>
</html>
http://jsfiddle.net/4fq6m3dc/3/
Related
I'm trying to loop through Google Place IDs and gather data from each place and then output the place details into one single JSON file which could later be imported into a map. The importing stage is not a concern but I'm struggling to get the data into the JSON file to begin with. What I have currently is below.
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places&key=APIKEY"></script>
var placeid_list = [{
"placeid": 'ChIJryijc9s0K4gRG9aU7SDTXdA',
}, {
"placeid": 'ChIJaZ6Hg4iAhYARxTsHnDFJ9zE',
}, {
"placeid": 'ChIJl64IQXrYzUwR8CVOTRf_h3o',
}, {
"placeid": 'ChIJBTMkuph-zkwR9oEF8Nv3Z0o',
}, {
"placeid": 'ChIJ4QbSBj8IzkwRGi0ILu03_VA',
}, {
"placeid": 'ChIJc2nSALkEdkgRkuoJJBfzkUI',
}, {
"placeid": 'ChIJmzrzi9Y0K4gRgXUc3sTY7RU',
}];
function setPlaces() {
var json = placeid_list;
for (var i = 0, length = json.length; i < length; i++) {
var data = json[i];
createPlace(data);
}
}
function createPlace(data) {
var service = new google.maps.places.PlacesService();
service.getDetails({
placeId: data.placeid
}, function (result, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
placeResults(data, result);
});
}
function placeResults(data, result) {
console.log(result.name);
}
Currently I'm just trying to output each of the Place names into a console.log but nothing seems to be showing. It doesn't look like I'm getting any errors in the console either so I'm not too sure where I'm going wrong.
Looking at Google's documentation, I'm not sure if I have to make use of
console.log(JSON.stringify(response.data));
Would this help me to put the details of each of the places into one large JSON file? I'm not too sure how I can implement it with what I currently have. I don't have a great deal of expertise in using javascript but I'm hoping that I'm not too far away from a solution. Thanks
You a typo in youre code:
var service = new google.maps.places.PlacesService();
Per the documentation:
Constructor
PlacesService(attrContainer)
Parameters:
attrContainer: HTMLDivElement|Map
Creates a new instance of the PlacesService that renders attributions in the specified container.
The PlacesService constructor has a required argument, either a google.maps.Map object or an HTMLDivElement that can be used to render attributions.
So the referenced line should be:
var service = new google.maps.places.PlacesService(map);
Or:
var service = new google.maps.places.PlacesService(document.getElementById("attributionDiv");
// where attributionDiv is a div that is displayed on your page
Proof of concept fiddle
Outputs:
Alo
Ottawa International Airport
lastminute.com London Eye
Four Seasons Hotel San Francisco
CN Tower
Glenn P Cowan, Chartered Professional Accountant
KB Media Corp
code snippet:
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: -33.866,
lng: 151.196
},
zoom: 15,
});
const request = {
placeId: "ChIJN1t_tDeuEmsRUsoyG83frY4",
fields: ["name", "formatted_address", "place_id", "geometry"],
};
const infowindow = new google.maps.InfoWindow();
const service = new google.maps.places.PlacesService(map);
var placeid_list = [{
"placeid": 'ChIJryijc9s0K4gRG9aU7SDTXdA',
}, {
"placeid": 'ChIJaZ6Hg4iAhYARxTsHnDFJ9zE',
}, {
"placeid": 'ChIJl64IQXrYzUwR8CVOTRf_h3o',
}, {
"placeid": 'ChIJBTMkuph-zkwR9oEF8Nv3Z0o',
}, {
"placeid": 'ChIJ4QbSBj8IzkwRGi0ILu03_VA',
}, {
"placeid": 'ChIJc2nSALkEdkgRkuoJJBfzkUI',
}, {
"placeid": 'ChIJmzrzi9Y0K4gRgXUc3sTY7RU',
}];
function setPlaces() {
var json = placeid_list;
for (var i = 0, length = json.length; i < length; i++) {
var data = json[i];
createPlace(data);
}
}
function createPlace(data) {
var service = new google.maps.places.PlacesService(map);
console.log(data);
service.getDetails({
placeId: data.placeid,
fields: ["name", "formatted_address", "place_id", "geometry"],
}, function(result, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
placeResults(data, result);
});
}
function placeResults(data, result) {
console.log(result.name);
document.getElementById("placeResults").innerHTML += result.name + "<br>";
}
setPlaces();
}
window.initMap = initMap;
/*
* Always set the map height explicitly to define the size of the div element
* that contains the map.
*/
#map {
height: 50%;
}
/*
* Optional: Makes the sample page fill the window.
*/
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<title>Place Details</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="placeResults"></div>
<div id="map"></div>
<!--
The `defer` attribute causes the callback to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises
with https://www.npmjs.com/package/#googlemaps/js-api-loader.
-->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=places&v=weekly" defer></script>
</body>
</html>
The pagination would not update itself as the filter applied. Data is loaded from the database using a Python script. I'm new to AngularJS. How do I change the code to solve this problem?
I tried to solve the problem by the link: Filter through pagination angular
Failed to deal :(
Corrected code ↓
<!-- language: lang-json -->
// **Listing index.json**
[{
"name": "265/70R16 112T Ice Zero",
"width": "265",
"height": "70",
"razmer": "R16",
"price": 112,
"model":"Ice Zero",
"brand":"Pirelli"
},
{
"name": "225/55R17 112T Ice Maiz",
"width": "225",
"height": "55",
"razmer": "R17",
"price": 102,
"model":"Ice Maiz",
"brand":"Continental"
},
{
"name": "205/50R16 112T PSX",
"width": "205",
"height": "50",
"razmer": "R16",
"price": 92,
"model":"PSX",
"brand":"Bridgstoun"
},
{
"name": "205/55R17 112T Brrr",
"width": "205",
"height": "55",
"razmer": "R17",
"price": 100,
"model":"Brrr",
"brand":"Toyo"
},
{
"name": "225/55R17 112T ICE WinterSport",
"width": "225",
"height": "55",
"razmer": "R17",
"price": 102,
"model":"ICE WinterSport",
"brand":"Dunlop"
},
{
"name": "255/65R18 112T Winter",
"width": "255",
"height": "65",
"razmer": "R18",
"price": 122,
"model":"Winter",
"brand":"Nokian"
},
{
"name": "225/55R17 112T Hmit 5",
"width": "225",
"height": "55",
"razmer": "R17",
"price": 102,
"model":"Hmit 5",
"brand":"Kunho"
},
{
"name": "245/45R20 112T Ice Sport",
"width": "245",
"height": "45",
"razmer": "R20",
"price": 202,
"model":"Ice Sport",
"brand":"GoodYear"
}]
// **Listing index.js**
var app = angular.module('app', [])
.factory('pagination', function ($sce) {
var currentPage = 1;
var itemsPerPage = 3;
var pageMax = 12;
var pageTo = 0;
var pageFrom = 0;
var products = [];
var click_count_next = 0;
return {
setProducts: function (newProducts) {
products = newProducts
}, /* END of setProducts */
getPageProducts: function (num) {
var num = angular.isUndefined(num) ? 0 : num;
var first = itemsPerPage * num;
var last = first + itemsPerPage;
currentPage = num;
last = last > products.length ? (products.length) : last;
return products.slice(first, last);
}, /* END of getPageProducts */
getTotalPagesNum: function () {
return Math.ceil(products.length / itemsPerPage);
}, /* END of getTotalPagesNum */
getPaginationList: function (pcn) {
var pcn = angular.isUndefined(pcn) ? 0 : pcn;
var pagesNum = this.getTotalPagesNum();
var paginationList = [];
/*document.write(pagesNum);*/
paginationList.push({
name: $sce.trustAsHtml('«'),
link: 'prev'
});
if (pageMax < pagesNum) {
if (pcn > Math.ceil(pageMax / 2) + pageFrom) {
pageFrom++;
pageTo = pageMax + pageFrom;
if (pageTo > pagesNum) {
pageTo = pagesNum;
pageFrom = pagesNum - pageMax;
}
}
if (pcn < Math.ceil(pageMax / 2) + pageFrom) {
pageTo--;
pageFrom = pageTo - pageMax;
if (pageFrom < 0) {
pageFrom = 0;
pageTo = pageMax;
}
}
if (pageTo <= pagesNum) {
for (var i = pageFrom; i < pageTo; i++) {
var name = i + 1;
paginationList.push({
name: $sce.trustAsHtml(String(name)),
link: i
});
};
}
}
else {
for (var i = 0; i < pagesNum; i++) {
var name = i + 1;
paginationList.push({
name: $sce.trustAsHtml(String(name)),
link: i
});
};
}
paginationList.push({
name: $sce.trustAsHtml('»'),
link: 'next'
});
if (pagesNum > 1) {
return paginationList;
} else {
return null;
}
}, /* END of getPaginationList */
getUpdatePagination: function () {
return this.getPaginationList(click_count_next)
},
getPrevPageProducts: function () {
var prevPageNum = currentPage - 1;
if (prevPageNum < 0) prevPageNum = 0;
this.getPageProducts(prevPageNum);
return currentPage;
}, /* END of getPrevPageProducts */
getNextPageProducts: function () {
var nextPageNum = currentPage + 1;
var pagesNum = this.getTotalPagesNum();
if (nextPageNum >= pagesNum) nextPageNum = pagesNum - 1;
this.getPageProducts(nextPageNum);
return currentPage;
}, /* END of getNextPageProducts */
getCurrentPageNum: function () {
return currentPage;
}, /* END of getCurrentPageNum */
}
}) /* END of factory-pagination */
///// CONTROLLER START
.controller('mainCtrl', function ($scope, $http, $filter, pagination) {
$http.get('https://mesnalex.com/stackoverflow/index.json')
.success(function(data){
$scope.products = $scope.ProductObj = data;
$scope.filterProducts = function () {
var chain = new filterChain($scope.ProductObj);
$scope.products = chain
.applyFilter('filter', [{ brand: $scope.brand }])
.applyFilter('filter', [{ razmer: $scope.razmer }])
.applyFilter('filter', [{ width: $scope.width }])
.applyFilter('filter', [{ height: $scope.height }])
.value;
pagination.setProducts($scope.products);
$scope.products = pagination.getPageProducts($scope.currentPage);
$scope.paginationList = pagination.getPaginationList($scope.page_click_next);
};
pagination.setProducts($scope.products);
$scope.products = pagination.getPageProducts($scope.currentPage);
$scope.paginationList = pagination.getPaginationList($scope.page_click_next);
$scope.showPage = function (page) {
if (page == 'prev') {
$scope.products = pagination.getPageProducts(page = pagination.getPrevPageProducts());
$scope.paginationList = pagination.getPaginationList(page);
}
else if (page == 'next') {
$scope.products = pagination.getPageProducts(page = pagination.getNextPageProducts());
$scope.paginationList = pagination.getPaginationList(page);
} else {
$scope.products = pagination.getPageProducts(page);
$scope.paginationList = pagination.getPaginationList(page);
}
}
$scope.currentPageNum = function () {
return pagination.getCurrentPageNum();
}
function filterChain(value) {
this.value = value;
}
filterChain.prototype.applyFilter = function (filterName, args) {
args.unshift(this.value);
this.value = $filter(filterName).apply(undefined, args)
return this;
};
});
});
///// CONTROLLER END
app.filter('unique', function () {
return function (items, filterOn) {
if (filterOn === false) {
return items;
}
if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
var hashCheck = {}, newItems = [];
var extractValueToCompare = function (item) {
if (angular.isObject(item) && angular.isString(filterOn)) {
return item[filterOn];
} else {
return item;
}
};
angular.forEach(items, function (item) {
var valueToCheck, isDuplicate = false;
for (var i = 0; i < newItems.length; i++) {
if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
newItems.push(item);
}
});
items = newItems;
}
return items;
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.23/angular.min.js"></script>
<!-- **Listing index.html** -->
<!-- some code -->
<body ng-app="app" ng-controller="mainCtrl">
<!--<div class="my_blog"><h2>My Blog</h2> -->
<!-- FILTER BOX START -->
<select ng-model="brand" ng-change="filterProducts()" style="margin-top:35px;width:210px;" autocomplete="off">
<option style="color:gray;" value="{{undefined}}">All</option>
<option ng-repeat="item in ProductObj | unique: 'brand' | orderBy: 'brand'" id="brand_Select" >{{ item.brand }}</option>
</select>
<select ng-model="height" ng-change="filterProducts()" style="float:left;margin-top:35px;width:210px;" autocomplete="off">
<option style="color:gray;" value="{{undefined}}">All</option>
<option ng-repeat="item in ProductObj | unique: 'height' | orderBy: 'height'" id="height_Select" >{{ item.height }}</option>
</select>
<!-- FILTER BOX END -->
<!-- LISTING PRODUCTS START -->
<div ng-repeat="item in products">
<div>
<h5>{{ item.brand }} {{ item.model }}</h5>
<h5>{{ item.name }}</h5>
<h5>{{ item.price }}</h5>
</div>
</div>
<!-- LISTING PRODUCTS END -->
<!-- PAGINATION START -->
<ul class="pagination">
<li class="page-item" ng-repeat="page in paginationList" ng-click="showPage(page.link)" ng-class="{'active': currentPageNum() == page.link}"><a class="page-link" ng-bind-html="page.name"></a></li>
</ul>
<!-- PAGINATION END -->
</body>
<!-- some code -->
Problem solved! :)
Changes that I made to the controller(for 4 filters):
.controller('mainCtrl', function ($scope, $http, $filter, pagination) {
$http.get('./out_data.php?action=getPosts')
.success(function(data){
$scope.products = $scope.ProductObj = data;
$scope.filterProducts = function () {
var chain = new filterChain($scope.ProductObj);
$scope.products = chain
.applyFilter('filter', [{ brand: $scope.brand }])
.applyFilter('filter', [{ razmer: $scope.razmer }])
.applyFilter('filter', [{ width: $scope.width }])
.applyFilter('filter', [{ height: $scope.height }])
.value;
pagination.setProducts($scope.products);
$scope.products = pagination.getPageProducts($scope.currentPage);
$scope.paginationList = pagination.getPaginationList($scope.page_click_next);
};
pagination.setProducts($scope.products);
$scope.products = pagination.getPageProducts($scope.currentPage);
$scope.paginationList = pagination.getPaginationList($scope.page_click_next);
function filterChain(value) {
this.value = value;
}
filterChain.prototype.applyFilter = function (filterName, args) {
args.unshift(this.value);
this.value = $filter(filterName).apply(undefined, args)
return this;
};
});
The changes I made to the getPaginationList function:
getPaginationList: function (pcn) {
var pcn = angular.isUndefined(pcn) ? 0 : pcn;
var pagesNum = this.getTotalPagesNum();
var paginationList = [];
/*document.write(pagesNum);*/
paginationList.push({
name: $sce.trustAsHtml('«'),
link: 'prev'
});
if (pageMax < pagesNum) {
if (pcn > Math.ceil(pageMax / 2) + pageFrom) {
pageFrom++;
pageTo = pageMax + pageFrom;
if (pageTo > pagesNum) {
pageTo = pagesNum;
pageFrom = pagesNum - pageMax;
}
}
if (pcn < Math.ceil(pageMax / 2) + pageFrom) {
pageTo--;
pageFrom = pageTo - pageMax;
if (pageFrom < 0) {
pageFrom = 0;
pageTo = pageMax;
}
}
if (pageTo <= pagesNum) {
for (var i = pageFrom; i < pageTo; i++) {
var name = i + 1;
paginationList.push({
name: $sce.trustAsHtml(String(name)),
link: i
});
};
}
}
else {
for (var i = 0; i < pagesNum; i++) {
var name = i + 1;
paginationList.push({
name: $sce.trustAsHtml(String(name)),
link: i
});
};
}
paginationList.push({
name: $sce.trustAsHtml('»'),
link: 'next'
});
if (pagesNum > 1) {
return paginationList;
} else {
return null;
}
}, /* END of getPaginationList */
Corrections to index.html:
<select ng-model="brand" ng-change="filterProducts()" style="margin-top:15px;width:210px;" autocomplete="off">
<option style="color:gray;" value="{{undefined}}">All</option>
<option ng-repeat="item in ProductObj | unique: 'brand' | orderBy: 'brand'" id="brand_Select" >{{ item.brand }}</option>
</select>
....
<div ng-repeat="item in products">
<div class="thumbnail">
<h5>{{ item.brand }} {{ item.model }}</h5>
<h5>{{ item.full_name }}</h5>
<h5>{{ item.roz_price }}</h5>
</div>
</div>
I have checked all stackoverflow posts related to ui-grid sorted rows without any success so I am opening one more question.
SHORT : Need a way to get sorted rows following current sorting criteria.
My problem is that I have an instance of UI Grid with pagination and I can not get the sorted data after it was added using a $mdDialog modal. It is shown at the right position in the tabel, but behind, in all objects it is stored the new element is on the last position.
I call the ui-grid instance using a service to keep all stuff in one place:
// Default service for init a ui-grid instance
app.serivce('testService', function(){
var defaultGridOptions = {
enableColumnMenus: false,
enablePaginationControls: true,
paginationPageSizes: [5],
multipleSorting: false,
treeRowHeaderAlwaysVisible: false,
paginationPageSize: 5,
enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
enableVerticalScrollbar: uiGridConstants.scrollbars.NEVER
};
// Each columns sort rule
// Position 0 from columnsOrder sorts position 0 from columnDefs and so on
var defaultColSort = [{
sort: { direction: uiGridConstants.ASC, priority: 0 }
}];
this.createGridOptions = function (gridData, columnDefs, gridOpts) {
gridOpts = typeof gridOpts !== 'undefined' ? gridOpts : {};
var gridOptions = angular.extend({}, defaultGridOptions, gridOpts);
for(var i = 0; i < defaultColSort.length; i++)
columnDefs[i] = angular.extend({}, defaultColSort[i], columnDefs[i]);
gridOptions.data = gridData;
gridOptions.columnDefs = columnDefs;
return gridOptions;
};
// The metod that should move to the desired page
this.jumpToGridItem = function(api, entry) {
var idx = -1;
var page = 0;
var sortedData = null;
// NEED A WAY TO GET SORTED DATA HERE
//idx = sortedData.indexOf(entry); -> checks the position of the new added item
if (idx == -1)
return false;
// Calculate the page where the element exists
page = Math.ceil(idx/api.grid.options.paginationPageSize);
// Jump to page
api.pagination.seek(page);
};
})
Here is my controller :
app.controller('testController', ['$scope', '$mdDialog', 'testService', function($scope, $mdDialog, testService){
var columnDefs = [
{
field: 'identifier',
name: 'Identifier'
}
];
var dummyData = [{ identifier: "Item" }, { identifier: 'Item 1' }, { identifier: "Item 2" }, { identifier: "Item 3" }];
var gridOptions = $scope.gridOptions = testService.createGridOptions(dummyData, columnDefs);
gridOptions.onRegisterApi = function (gridApi) {
$scope.gridApi = gridApi;
};
$scope.add = function () {
$mdDialog.show({
controller: function($mdDialog) {
var data = $scope.identifierVal;
$mdDialog.hide(data);
},
templateUrl: 'add.html',
parent: angular.element(document.body)
}).then(function (entry) {
// Data received when the modal is hidden
$scope.gridOptions.data.push(entry);
testService.jumpToGridItem($scope.gridApi, entry);
});
};
}]);
Right now I am appending the data with push(), this could be one reason, I think.
The method I have to update is jumpToGridItem, which actually should focus the page where the item was added.
Thank you
PS : Sorry for not posting a plnkr, I will do bit later if it is needed.
I finally found a way to achieve what I initially wanted. I ve found it a day after posting the question but I was busy enough to post the answer. The code below can be also found in a plnkr. It looks for a certain entry and goes to the page where it can be found.
I wanted this to focus a dynamically added entry in a ui-grid table from a dialog (modal form):
Controller :
var app = angular.module('stefanz', ['ui.grid', 'ui.grid.pagination']);
app.controller('MyCtrl', ['$scope', 'UIGridCustom', '$http', function($scope, UIGridCustom, $http){
// A part of data copied from ui-grid demos
var data = [{"name": "Ethel Price", "gender": "female", "company": "Enersol" },{"name": "Claudine Neal", "gender": "female", "company": "Sealoud" },{"name": "Beryl Rice", "gender": "female", "company": "Velity" },{"name": "Wilder Gonzales", "gender": "male", "company": "Geekko" },{"name": "Georgina Schultz", "gender": "female", "company": "Suretech" },{"name": "Carroll Buchanan", "gender": "male", "company": "Ecosys" },{"name": "Valarie Atkinson", "gender": "female", "company": "Hopeli" },{"name": "Schroeder Mathews", "gender": "male", "company": "Polarium" },{"name": "Lynda Mendoza", "gender": "female", "company": "Dogspa" },{"name": "Sarah Massey", "gender": "female", "company": "Bisba" },{"name": "Robles Boyle", "gender": "male", "company": "Comtract" },{"name": "Evans Hickman", "gender": "male", "company": "Parleynet" },{"name": "Dawson Barber", "gender": "male", "company": "Dymi" }];
var colDefs = [{
label: "name",
name: "name"
}, {
label: "gender",
name: "gender"
}, {
label: "company",
name: "company"
}];
// Call the service for init
var gridOptions = $scope.gridOptions = UIGridCustom.createGridOptions(data, colDefs);
gridOptions.onRegisterApi = function(api) {
$scope.gridApi = api;
}
$scope.getItemPage = function(name) {
UIGridCustom.jumpToGridItem($scope.gridApi, name);
}
}]);
app.service('UIGridCustom', ['uiGridConstants', 'utils', function(uiGridConstants, utils){
var defaultGridOptions = {
enableColumnMenus: false,
enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
enableVerticalScrollbar: uiGridConstants.scrollbars.NEVER,
enablePaginationControls: false,
paginationPageSize: 5,
multipleSorting: true
};
// Each columns sort rule
// Position 0 from columnsOrder sorts position 0 from columnDefs and so on
// Could be overwritten into columnDefs
// Docs : http://ui-grid.info/docs/#/api/ui.grid.class:GridOptions
var defaultColSort = [];
//1st column default sorting
defaultColSort[{
sort: { direction: uiGridConstants.ASC, priority: 0 }
}];
// For sorting 2nd column
// defaultColSort[1] = {
// sort: { direction: uiGridConstants.ASC, priority: 0 }
// };
this.createGridOptions = function (gridData, columnDefs, stefanzGridOpts) {
// Overwrite defaults with custom passed options for grid
var stefanzGridOpts = typeof stefanzGridOpts !== 'undefined' ? stefanzGridOpts : {};
var gridOptions = angular.extend({}, defaultGridOptions, stefanzGridOpts);
// Force sorting following the default/custom column sort
for(var i = 0; i < defaultColSort.length; i++)
columnDefs[i] = angular.extend({}, defaultColSort[i], columnDefs[i]);
// Grid init
gridOptions.data = gridData;
gridOptions.columnDefs = columnDefs;
return gridOptions;
};
this.jumpToGridItem = function(api, name) {
var idx = 0;
var page = 0;
var sorting = prepareCriteria(api.grid.getColumnSorting());
var data = dataObjectSort(prepareRows(api.grid.rows), sorting);
entry = getEntryByName(data, name);
idx = data.indexOf(entry) + 1;
if (!idx)
return false;
// Calculate the page where the element exists
page = Math.ceil(idx/api.grid.options.paginationPageSize);
alert(name + 'is found on page ' + page);
// Jump to page
api.pagination.seek(page);
};
// Takes the row's entity and put in a new array as a top-level item
// Userful for further data handling
var prepareRows = function(rows) {
if (rows.length == 0)
return false;
var preparedRows = [];
rows.forEach(function(row){
// Do not need to handle the rows that are not in current filter (hidden)
if (row.visible == false)
return true;
preparedRows.push(row.entity);
});
return preparedRows;
};
// We are comparing whole enter and as a parameter we are sending a name
var getEntryByName = function(data, searchedName) {
for(var i = 0; i < data.length; i++) {
if (data[i]['name'] == searchedName)
return data[i];
}
return false;
}
var dataObjectSort = function(data, criteria) {
return data.sort(utils.dynamicSortMultiple(criteria));
};
var prepareCriteria = function(colSorting) {
var sorting = [];
var fields = [];
// Take just needed fields
colSorting.forEach(function(column){
sorting.push({
field: column.field,
direction: column.sort.direction,
priority: column.sort.priority
})
});
// Sort criterias by priority - UI grid works like this
// Reason : http://ui-grid.info/docs/#/api/ui.grid.class:GridOptions.columnDef#properties_sort
sorting.sort(function(a, b){
if (a.priority < b.priority) return -1;
else if (a.priority > b.priority) return 1;
else return 0;
});
// Prepare fields for sorting
sorting.forEach(function(sort){
// Dymanic sort (above) needs "-" sign for descendent direction
if (sort.direction != uiGridConstants.ASC)
sort.field = '-' + sort.field;
fields.push(sort.field);
});
return fields;
};
}]);
// Keep utils methods into a separate service
// Here all sorting methods will appear
app.service('utils', function(){
function getJsonValue(obj, path) {
if (!path || path == '')
return obj;
path = path.split('.');
var len = path.length;
for (var i = 0; i < len - 1; i++) {
var prop = path[i].split(/\[([^\]]+)]/); // indication[4] => [indication, 4]; indication => [indication]
if (prop.length == 1) {
obj = obj[prop[0]];
} else {
obj = obj[prop[0]][prop[1]];
}
}
var prop = path[len - 1].split(/\[([^\]]+)]/); // indication[4] => [indication, 4]; indication => [indication]
if (prop.length == 1) {
return obj[prop[0]];
} else {
if (prop.length == 2) {
return obj[prop[0]][prop[1]];
} else {
if(prop.length ==3) {
return obj[prop[0]][prop[1]]; // this is a hack!
} else {
return obj[prop[0]][prop[1]][prop[3]]; // this is a hack!
}
}
}
};
//http://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value-in-javascript/4760279#4760279
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
var aInsensitive = getJsonValue(a, property).toLowerCase();
var bInsensitive = getJsonValue(b, property).toLowerCase();
var result = (aInsensitive < bInsensitive) ? -1 : (aInsensitive > bInsensitive) ? 1 : 0;
return result * sortOrder;
}
};
function dynamicSortMultiple(props) {
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
};
return {
getJsonValue: function(obj, path) {
return getJsonValue(obj, path);
},
dynamicSort: function(property) {
return dynamicSort(property);
},
dynamicSortMultiple: function(props) {
return dynamicSortMultiple(props);
}
}
});
HTML
<!DOCTYPE html>
<html ng-app="stefanz">
<head>
<script data-require="angularjs_1_3_15#*" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.min.js"></script>
<script data-require="angularjs_1_3_15#*" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular-animate.min.js"></script>
<script data-require="angularjs_1_3_15#*" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular-aria.min.js"></script>
<script data-require="jquery#*" data-semver="2.1.4" src="https://code.jquery.com/jquery-2.1.4.js"></script>
<link data-require="ui-grid#*" data-semver="3.0.7" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.0.7/ui-grid.css" />
<script data-require="ui-grid#*" data-semver="3.0.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.0.7/ui-grid.js"></script>
<script data-require="bootstrap#~3.3.5" data-semver="3.3.6" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MyCtrl">
<div ui-grid="gridOptions" ui-grid-pagination class="grid"></div>
<div class="centerAlignedText">
<ul>
<li><a ng-click="getItemPage('Ethel Price')">Get Ethel Price</a></li>
<li><a ng-click="getItemPage('Schroeder Mathews')">Get Schroeder Mathews</a></li>
<li><a ng-click="getItemPage('Dawson Barber')">Get Dawson Barber</a></li>
<li><a ng-click="getItemPage('Sarah Massey')">Get Sarah Massey</a></li>
</ul>
</div>
<div class="centerAlignedText" ng-if="gridOptions.totalItems > 0">
<div class="paginationButtonsIcon boldText" style="width: 100px; display: inline-block;">
<md-button ng-if="gridApi.pagination.getPage() > 1" class="paginationButtons" ng-click="gridApi.pagination.previousPage()" style="width: 90px;">
<span class="notTransformedText boldText">Previous</span>
</md-button>
</div>
<div ng-repeat="n in gridApi.pagination.getTotalPages()" style="display: inline-block;">
<md-button ng-if="(gridApi.pagination.getTotalPages() < 11)
|| (gridApi.pagination.getPage() < 7 && n < 10)
|| (n > gridApi.pagination.getPage() - 7 && n < gridApi.pagination.getPage() + 4)
|| (gridApi.pagination.getPage() > gridApi.pagination.getTotalPages() - 5 && n > gridApi.pagination.getTotalPages() - 11)" class="paginationButtons md-mini md-icon-button md-primary" ng-click="gridApi.pagination.seek($index + 1)">
<span class="paginationButtonsIcon boldText" ng-if="gridApi.pagination.getPage() === $index + 1">
{{$index + 1}}
</span>
<span class="paginationButtonsIcon" ng-if="gridApi.pagination.getPage() !== $index + 1">
{{$index + 1}}
</span>
</md-button>
</div>
<div class="paginationButtonsIcon boldText" style="width: 100px; display: inline-block;">
<md-button ng-if="gridApi.pagination.getPage() < gridApi.pagination.getTotalPages()" class="paginationButtons md-icon-button md-primary" ng-click="gridApi.pagination.nextPage()" style="width: 90px;">
<span class="notTransformedText boldText">Next</span>
</md-button>
</div>
</div>
</body>
</html>
I'm trying to create a dynamic chart from userTemplate object.
I'm using this directive angular-flot and I want create the dataset and options of directive dynamically.
Its work but I have this error
Error: [$rootScope:infdig] http://errors.angularjs.org/1.2.21/$rootScope/infdig?p0=10&p1=%5B%5B%22fn%3…ection%5C%22%3A%7B%5C%22color%5C%22%3A%5C%22%2354728c%5C%22%7D%7D%22%5D%5D
at Error (native)
at http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:6:450
at k.$get.k.$digest (http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:110:66)
at k.$get.k.$apply (http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:112:173)
at http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:122:253
at e (http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:37:440)
at http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:41:120
HTML
<div ng-repeat="panel in row.panels" class="{{panel.columnClass}}" resizable id="{{panel.id}}" r-directions="['right']">
<flot dataset="getDataForChart(panel)" options="getOptionForChart(panel)" height="{{panel.graph.height}}"></flot>
</div>
CONTROLLER
$scope.userTemplate = [
{
blockId: 'blockUno',
title: 'Block title',
rows: [
{
rowId: 'rowUno',
title: 'Row Title 1',
panels: [
{
id: 'palel-report-1',
title: 'uno',
columnClass: 'col-md-4',
graph: {
height: 250,
type: "BAR",
countBy: "status"
}
},
{
id: 'palel-report-2',
title: 'due',
columnClass: 'col-md-4',
graph: {
height: 250,
type: "PIE",
countBy: "status"
}
},
{
id: 'palel-report-3',
title: 'tre',
columnClass: 'col-md-4',
graph: {
height: 250,
type: "BAR",
countBy: "status"
}
}
]
}
],
tables: []
}
];
$scope.getDataForChart = function(panel) {
var graphData = [];
var countBy = panel.graph.countBy;
var arr = $scope.reportingData;
for (var i = 0; i < arr.length; i++) {
var valueOfkey = arr[i][countBy];
graphData.push(valueOfkey);
}
var a = [], b = [], prev;
graphData.sort();
for (var i = 0; i < graphData.length; i++) {
if (graphData[i] !== prev) {
a.push(graphData[i]);
b.push(1);
} else {
b[b.length - 1]++;
}
prev = graphData[i];
}
var graphData = [];
for (var i = 0; i < a.length; i++) {
var singleO = {label: '' + a[i], data: [[i, b[i]]]};
graphData.push(singleO);
}
return graphData;
};
$scope.getOptionForChart = function(panel) {
var options = angular.copy($scope.defaultPlotOptions);
var typeGraph = panel.graph.type;
switch (typeGraph) {
case "BAR":
options.series.bars.show = true;
break;
case "LINE":
options.series.lines.show = true;
break;
case "PIE":
options.series.pie.show = true;
break;
case "POINT":
options.series.points.show = true;
break;
case "TABLE":
break;
}
return options;
};
The error you get is from an infinite digest loop.
In a couple of places you are calling functions that return new items each time. Here's an example from the docs linked from the error message you received that suggests this may cause this error:
One common mistake is binding to a function which generates a new
array every time it is called. For example:
<div ng-repeat="user in getUsers()">{{ user.name }}</div>
$scope.getUsers = function() { return [ { name: 'Hank' }, { name: 'Francisco' } ]; };
Since getUsers() returns a new array, Angular
determines that the model is different on each $digest cycle,
resulting in the error. The solution is to return the same array
object if the elements have not changed:
var users = [ { name: 'Hank' }, { name: 'Francisco' } ];
$scope.getUsers = function() { return users; };
In your code, you are doing the same binding to getDataForChart and getOptionForChart.
I am new to angularjs and I would like to understand what the directives do but I can't find a tutorial with different example by complexity and I was curios if I could move the following code in a directive.
This is my javascript file(controller.js):
function TestCtrl(){
var json = {
id:"judge_id",
name:"Test",
children: [ {
id:"filter_1",
name:'Filter 1',
children:[{id:"case_1",name:"CaseA",children:[]},{id:"case_2",name:"CaseB",children:[]},{id:"case_3",name:"CaseC",children:[]}]
},
{
id:"filter_2",
name:'Filter 2',
children:[]
},
{
id:"filter_3",
name:'Filter 3',
children:[]
},
{
id:"filter_4",
name:'Filter 4',
children:[]
},
{
id:"filter_5",
name:'Filter 5',
children:[]
},
{
id:"filter_6",
name:'Filter 6',
children:[]
}
]
};
var rgraph = new $jit.RGraph({
//Where to append the visualization
injectInto: 'infovis',
background: {
CanvasStyles: {
strokeStyle: '#555'
}
},
//Add navigation capabilities:
//zooming by scrolling and panning.
Navigation: {
enable: true,
panning: true,
zooming: 10
},
//Set Node and Edge styles.
Node: {
color: '#ddeeff'
},
Edge: {
color: '#C17878',
lineWidth:1.5
},
//Add the name of the node in the correponding label
//and a click handler to move the graph.
//This method is called once, on label creation.
onCreateLabel: function(domElement, node){
domElement.innerHTML = node.name;
domElement.onclick = function(){
rgraph.onClick(node.id, {
onComplete: function() {
Log.write("done");
}
});
};
},
//Change some label dom properties.
//This method is called each time a label is plotted.
onPlaceLabel: function(domElement, node){
var style = domElement.style;
style.display = '';
style.cursor = 'pointer';
if (node._depth <= 1) {
style.fontSize = "0.8em";
style.color = "#ccc";
} else if(node._depth == 2){
style.fontSize = "0.7em";
style.color = "#494949";
} else {
style.display = 'none';
}
var left = parseInt(style.left);
var w = domElement.offsetWidth;
style.left = (left - w / 2) + 'px';
}
});
//load JSON data
rgraph.loadJSON(json);
//trigger small animation
rgraph.graph.eachNode(function(n) {
var pos = n.getPos();
pos.setc(-200, -200);
});
rgraph.compute('end');
rgraph.fx.animate({
modes:['polar'],
duration: 2000
});
}
ANd my html file is like this:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="http://philogb.github.io/jit/static/v20/Jit/jit-yc.js"></script>
<script src="..js/controller.js"></script>
<link type="text/css" href="../base.css" rel="stylesheet" />
<title></title>
</head>
<body onload="TestCtrl();">
<div id="center-container">
<div id="infovis"></div>
</div>
</body>
</html>
Thanks
Sabbu