Synchronize Leafletjs map data with Angularjs - javascript

I'm trying to create an app that takes latitude and longitude coordinates (along with other properties) from a json file and apply them to my map, along with filter and search options. I was following along with this tutorial: http://zevross.com/blog/2014/05/27/synchronize-leaflet-map-data-with-angularjs/
I can't figure out if my json file is not formatted correctly or if I'm not iterating over the file right in my javascript. Thanks for any help on this.
controllers.js
'use strict';
myApp.controller('DemoController', ["$scope", "$http", '$q', '$filter',
function($scope, $http, $q, $filter) {
$scope.search = {
customer: '',
year: ''
}
$scope.tableClick = function(dat){
$scope.search.customer = dat.customer
}
// function countryClick(country, event) {
// console.log(country);
// }
$scope.orderByField = 'year';
$scope.$on("leafletDirectiveMap.geojsonMouseover", function(ev,
leafletEvent) {
customerMouseover(leafletEvent);
});
$scope.$on("leafletDirectiveMap.geojsonClick", function(ev,
featureSelected, leafletEvent) {
$scope.search.customer=featureSelected.properties.customer
});
$scope.clearSelections = function(){
$scope.search.customer = ''
$scope.search.year = ''
}
$scope.$watchCollection("search",
function(newValue, oldValue) {
if (newValue === oldValue) {
return;
}
var data = angular.copy($scope.acct_year);
var justGroup = _.filter(data.features, function(x) {
if (newValue.year == '' || newValue.year == undefined) {
if (!newValue.customer) {
return true
} else {
return $filter('filter')([x.properties.customer],
newValue.customer).length > 0
}
} else {
if (!newValue.customer) {
return x.properties.year == newValue.year
} else {
return x.properties.year == newValue.year & $filter('filter')([x.properties.customer], newValue.customer).length > 0
}
}
})
data.features = justGroup
$scope.geojson = {
data: data,
style: style,
resetStyleOnMouseout: true
}
}
);
angular.extend($scope, {
center: {
lat: 40.8471,
lng: 14.0625,
zoom: 2
},
scrollWheelZoom: false,
legend: {
colors: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f'],
labels: ['2010', '2011', '2012', '2013', '2014', '2015']
}
});
var opac = 0.8
var circlecolors = {
'2010': {
color: '#7fc97f',
opacity: opac
},
'2011': {
color: '#beaed4',
opacity: opac
},
'2012': {
color: '#fdc086',
opacity: opac
},
'2013': {
color: '#ffff99',
opacity: opac
},
'2014': {
color: '#386cb0',
opacity: opac
},
'2015': {
color: '#f0027f',
opacity: opac
}
}
function getColorFootball(d) {
return circlecolors[d.year] || {
color: 'grey',
opacity: 0
}
}
function style(feature) {
var vals = getColorFootball($scope.footballObject[feature.properties.ISO3])
var rads = getRadiusFootball($scope.footballObject[feature.properties.ISO3])
return {
fillColor: vals.color,
radius: rads,
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: vals.opacity
};
}
function getRadiusFootball(d) {
if (d) {
d = d['year']
return Math.sqrt(1500 / d)
} else {
return 0
}
}
$scope.acct_year= [];
$http.get('acct_year_small.json').success(function(data, status) {
var tempAcct_Json = {};
for (var i = 0; i < data.length; i++) {
var customer = data[i];
tempAcct_Json[customer['CUSTOMER']] = customer;
//then set on scope
$scope.footballObject = tempAcct_Json;
$scope.acct_year = data;
}
});
// http://thematicmapping.org/downloads/world_borders.php
// qgis to do centroids, move US, save as geojson
$scope.acct_yeargeo = {};
$http.get("world.geojson").success(function(data, status) {
//data.features = data.sort(propSort(["PARK_NAME"]));
var featuresLim = []
var minrank = 0
for (var i = 0; i < data.features.length; i++) {
var amatch = _.where($scope.acct_year, {
"alpha-3": data.features[i].properties['ISO3']
})
if (amatch.length > 0) {
var feat = data.features[i]
var currank = amatch[0]['year']
var curgroup = amatch[0]['year']
var curcountry = amatch[0]['customer']
feat.properties['year'] = currank
feat.properties['year'] = curgroup
feat.properties['customer'] = curcountry
featuresLim.push(feat)
} //end if
} //end loop through features
featuresLim.sort(propSort("year"));
//featuresLim.sort(sortBy)
data.features = featuresLim
$scope.acct_yeargeo = data
angular.extend($scope, {
geojson: {
data: data,
style: style,
resetStyleOnMouseout: true
}
}); //end extend
}); //end get features
function countryMouseover(leafletEvent) {
var layer = leafletEvent.target;
layer.setStyle({
weight: 2,
color: '#666',
fillColor: 'white'
});
//layer.bringToFront();
}
function propSort(props) {
return function sort(a, b) {
var p;
a = a.properties;
b = b.properties;
p = props;
if (a[p] < b[p]) return -1;
if (a[p] > b[p]) return 1;
};
}
}
]);
//mapoptions
myApp.controller("GoogleMapsController", ["$scope",
function($scope) {
angular.extend($scope, {
world: {
lat: 39.809860,
lng: -98.555183,
zoom: 4
},
scrollwheel: false,
layers: {
baselayers: {
googleTerrain: {
name: 'Google Terrain',
layerType: 'TERRAIN',
type: 'google'
}
}
},
defaults: {
scrollwheel: false
}
});
}
]);
test2.html
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8" />
<title>Map</title>
<link href="../css/bootstrap.min.css" rel="stylesheet" />
<link href="../css/leaflet.css" rel="stylesheet" />
<link rel="stylesheet" type="text/css"
href="http://cloud.github.com/downloads/lafeber/world-flags-
sprite/flags32.css" />
<script src="http://maps.google.com/maps/api/js?v=3.2&sensor=false">
</script>
<script
src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-
min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"
rel="stylesheet">
<link rel="stylesheet" href="../css/app.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>
</head>
<body ng-controller="DemoController">
<div class="container">
<div class="row">
<h1>Map</h1>
</div>
<div class="row">
<div ng-controller='GoogleMapsController'>
<!-- <leaflet center="center" events="events" legend="legend"
geojson="geojson" width='100%' height='600'></leaflet> -->
<leaflet center="world" events="events" legend="legend"
width='100%' height='400' layers='layers' geojson="geojson"></leaflet>
</div>
<div class="info country f32">
<div ng-show="geojson.selected" class="flag" ng-
class="geojson.selected.properties.ISO2|lowercase"></div>
<span class='countryselected' ng-cloak>{{
geojson.selected.properties.NAME ?
geojson.selected.properties.NAME + ' — Years ' +
footballObject[geojson.selected.properties.ISO3].year : 'Select
customer on map'}}</span>
</div>
<!-- <div class="info box">Map center: [ lat: {{ center.lat |
number:4 }}, lng: {{ center.lng | number:4 }} ]</div> -->
<div class="col-md-10 col-md-offset-1">
<div class="row well filtering">
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="search" class="col-sm-6 control-
label">Filter by Customer</label>
<input ng-model="search.country">
</div>
<div class="form-group">
<label class="col-sm-6 control-label">Filter by
Year</label>
<select class="selectpicker" ng-model='search.Group'
ng-options="city.Group as city.Group for city in acct_year | unique:'year'
| orderBy:'year'" fix>
<option value="" selected="selected">-- All Years --</option>
</select>
</div>
<div class="form-group">
<button type="button" class="btn btn-grey col-sm-2 col-sm-
offset-5" ng-click='clearSelections()'>Clear
Selections</button>
</div>
</form>
</div>
<div class="row">
<table ng-cloak class='table table-striped full'>
<thead>
<tr class="foot">
<th><a href="" ng-click="orderByField =
'customer'; reverse=!reverse">Customer</a>
</th>
<th><a href="" ng-click="orderByField =
'cust_code'; reverse=!reverse">Customer Code</a>
</th>
<th><a href="" ng-click="orderByField = 'grand
total'; reverse=!reverse">Grand Total</a>
</th>
<th><a href="" ng-click="orderByField = 'year';
reverse=!reverse">Year</a>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="foot in acct_year |
orderBy:orderByField:reverse | filter:search" ng-
click="tableClick(foot)">
<td class='country'>{{foot.customer}}</td>
<td>{{foot.cust_code}}</td>
<td>{{foot.grand_total}}</td>
<td>{{foot.year}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<hr>
<footer>
</footer>
</div>
</body>
<script>
</script>
<script src="../js/angular.min.js"></script>
<script src="../js/angular-route.js"></script>
<script src="../js/angular-leaflet-directive.js"></script>
<script src="../js/app.js"></script>
<script src="../js/controllers.js"></script>
<script src="../js/directives.js"></script>
<script src="../js/filters.js"></script>
<script src="../js/Google.js"></script>
</body>
acct_year_small.json (just a testing file, actual file has much more data)
features =
[
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ -102.852,30.877528 ]
},
"properties": {
"CUSTOMER":"Bridgestone Americas Tire Operations",
"CUST_CODE":20,
"GRAND TOTAL":"$11,311.82",
"YEAR":2010
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ -76.41533,39.337798 ]
},
"properties": {
"CUSTOMER":"D & M Equipment",
"CUST_CODE":47,
"GRAND TOTAL":"$4,500.00",
"YEAR":2010
}
}
];

If your JSON file is correct, you need to change
tempAcct_Json[customer['CUSTOMER']] = customer;
to
tempAcct_Json[customer.properties['CUSTOMER']] = customer;

Related

Problems with chart.js using Laravel 7, Cannot find element: #app?

I'm using chart.js for showing statistics of reviews and messages of a user, but I'm getting problems with the scripts, now the stats are working but I got this error Cannot find element: #app and I don't know how to manage that.
If I use defer in this script (now I deleted it to see the stats working, but all the rest of the website don't)
<script src="{{ asset('js/app.js') }}"></script>
the stats doesn't work anymore and I get also another error like Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side effects in your templates, such as , as they will not be parsed.
So if I use defer i got errors, if I don't use defer it cannot find #app.
What should I do? Please help me, it's very important!
My app.blade.php file (where the script from before is)
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
{{-- <title>{{ config("app.name", "Bool n Roll") }}</title> --}}
<title>Bool 'n' Roll</title>
<script src="{{ asset('js/app.js') }}"></script>
<link rel="icon" href="{{asset('images/favicon.ico')}}" type="image/x-icon"/>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
<nav class="navbar navbar-expand-md shadow-sm bg-nav fixed-nav">
<div class="container">
<a class="navbar-brand" href="{{ url('/') }}">
<img style="height: 50px;" src="{{ asset('images/logorock.png') }}" alt="">
</a>
<button class="navbar-toggler bg-dark" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav mr-auto">
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Authentication Links -->
#guest
<li class="nav-item login-link rounded ml-2">
<a class="nav-link text-white px-2" href="{{ route('login') }}">{{ __('Login') }}</a>
</li>
#if (Route::has('register'))
<li class="nav-item register-link rounded ml-2">
<a class="nav-link title-orange px-2" href="{{ route('register') }}">{{ __('Sei un musicista? Registrati!') }}</a>
</li>
#endif
#else
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle title-orange" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{ ucfirst(Auth::user()->name) }}
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="/admin">
Dashboard
</a>
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
#csrf
</form>
</div>
</li>
#endguest
</ul>
</div>
</div>
</nav>
<main>
#yield('content')
</main>
<footer class="bg-dark text-white py-5">
<div class="container">
<div class="row text-center">
<div class="col-xs-12 col-md-4 col-lg-4">
<img style="height: 50px;" src="{{ asset('/images/footer-logo.png') }}" alt="">
<h5 class="my-3">Made with <span class="title-pink">♥</span> from Team 4</h5>
</div>
<div class="col-xs-12 col-md-4 col-lg-4">
<h5>Dev Team</h5>
<ul class="list-unstyled">
<li><a class="footer-list title-yellow" href="https://github.com/RobertoZeppilli">Roberto Zeppilli</a></li>
<li><a class="footer-list title-petrol" href="https://github.com/Edomak">Edoardo Maccherini</a></li>
<li><a class="footer-list title-orange" href="https://github.com/fabiopiro">Fabio Piroddi</a></li>
<li><a class="footer-list title-pink" href="https://github.com/michelafranchini">Michela Franchini</a></li>
</ul>
</div>
<div class="col-xs-12 col-md-4 col-lg-4">
<h5 class="my-3">Sei un musicista?</h5>
<ul class="list-unstyled">
<li class="nav-item register-link rounded">
<a class="nav-link title-orange" href="{{ route('register') }}">{{ __('Registrati subito!') }}</a>
</li>
</ul>
</div>
</div>
</div>
</footer>
</div>
#yield('script')
</body>
</html>
My stat view
Here I think I got major problems, maybe the script are not correct? Or there's a better way to place them inside the workflow?
#extends('layouts.app')
#section('content')
<div class="my_container">
<h1 class="stat_title">Le tue statistiche</h1>
#if (count($messages) == 0 && count($reviews) == 0)
<h2 id="empty_page">Non hai statistiche disponibili</h2>
#else
<div class="chart_1">
<h4>Numero di messaggi e recensioni ricevute ogni mese</h4>
<canvas id="myChart"></canvas>
</div>
<div class="chart_1">
<h4>Voti ricevuti ogni mese</h4>
<canvas id="myOtherChart"></canvas>
</div>
#endif
<p class="link_dashboard">Torna alla Dashboard</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js" integrity="sha512-Wt1bJGtlnMtGP0dqNFH1xlkLBNpEodaiQ8ZN5JLA5wpc1sUlk/O5uuOMNgvzddzkpvZ9GLyYNa8w2s7rqiTk5Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.10.6/dayjs.min.js" integrity="sha512-bwD3VD/j6ypSSnyjuaURidZksoVx3L1RPvTkleC48SbHCZsemT3VKMD39KknPnH728LLXVMTisESIBOAb5/W0Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>dayjs().format()</script>
<script>
dayjs().format()
var ctx = document.getElementById('myChart');
var ct2 = document.getElementById('myOtherChart');
var commenti = {!! $reviews->toJson() !!};
var messaggi = {!! $messages->toJson() !!};
// console.log(commenti.length);
// console.log(messaggi.length);
var now = dayjs();
if (commenti[0]) {
var primaDataCommento = commenti[0].created_at;
var date1 = dayjs(primaDataCommento);
} else {
var date1 = now;
}
const primaDataMessaggio = messaggi[0].created_at;
const date2 = dayjs(primaDataMessaggio);
var datex;
if (date2 < date1) {
datex = date2;
} else {
datex = date1;
}
var diff = now.diff(datex, 'month');
var diffRece = now.diff(date1, 'month');
var months = [];
var monthsRece = [];
var recensioniMese = [];
var messaggiMese = [];
var voto1 = [];
var voto2 = [];
var voto3 = [];
var voto4 = [];
var voto5 = [];
// prima tabella
var x = 1;
let i = 0;
if (datex.$M == 0) {
diff++;
i++;
x--;
}
for (i; i <= diff; i++) {
var numeroMese = datex.$M + i + x;
months.push(numeroMese + '/2021');
var countRec = 0;
var countMes = 0;
for (let j = 0; j < commenti.length; j++) {
if (numeroMese == dayjs(commenti[j].added_on).$M + 1) {
countRec++;
}
}
for (let j = 0; j < messaggi.length; j++) {
if (numeroMese == dayjs(messaggi[j].added_on).$M + 1) {
countMes++;
}
}
recensioniMese.push(countRec);
messaggiMese.push(countMes);
}
// seconda tabella
x = 1;
i = 0;
if (date1.$M == 0) {
diffRece++;
i++;
x--;
}
for (i; i <= diff; i++) {
var numeroMeseRece = date1.$M + i + x;
monthsRece.push(numeroMeseRece + '/2021');
var countRece1 = 0;
var countRece2 = 0;
var countRece3 = 0;
var countRece4 = 0;
var countRece5 = 0;
for (let j = 0; j < commenti.length; j++) {
if (numeroMeseRece == dayjs(commenti[j].created_at).$M + 1) {
switch (commenti[j].vote) {
case 1:
countRece1++;
break;
case 2:
countRece2++;
break;
case 3:
countRece3++;
break;
case 4:
countRece4++;
break;
case 5:
countRece5++;
break;
default:
break;
}
}
}
voto1.push(countRece1);
voto2.push(countRece2);
voto3.push(countRece3);
voto4.push(countRece4);
voto5.push(countRece5);
}
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: months,
datasets: [
{
label: 'Numero di recensioni',
data: recensioniMese,
backgroundColor: [
'#0000ff8c',
],
borderColor: [
'#0000ff',
],
borderWidth: 1
},
{
label: 'Numero di messaggi ricevuti',
data: messaggiMese,
backgroundColor: [
'#ff00c88c',
],
borderColor: [
'#ff00c8',
],
borderWidth: 1
},
]
},
options: {
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
}
}
});
var myChart = new Chart(ct2, {
type: 'bar',
data: {
labels: monthsRece,
datasets: [
{
label: 'Recensioni con voto 1',
data: voto1,
backgroundColor: [
'#ff00008c',
],
borderColor: [
'red',
],
borderWidth: 1
},
{
label: 'Recensioni con voto 2',
data: voto2,
backgroundColor: [
'#ffa6008c',
],
borderColor: [
'orange',
],
borderWidth: 1
},
{
label: 'Recensioni con voto 3',
data: voto3,
backgroundColor: [
'#ffff008c',
],
borderColor: [
'yellow',
],
borderWidth: 1
},
{
label: 'Recensioni con voto 4',
data: voto4,
backgroundColor: [
'#b7dd298c',
],
borderColor: [
'#b7dd29',
],
borderWidth: 1
},
{
label: 'Recensioni con voto 5',
data: voto5,
backgroundColor: [
'#57e32c8c',
],
borderColor: [
'#57e32c',
],
borderWidth: 1
},
]
},
options: {
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
}
}
});
</script>
#endsection
The app.js file
Maybe the problem is here? I was trying to wrap the vue instance inside an addEventListener('load') or something to load the instance later, but it didn't work.
require('./bootstrap');
window.Vue = require('vue');
import router from './router';
var dayjs = require('dayjs')
// dayjs().format()
import Vue from 'vue';
import VueCarousel from 'vue-carousel';
Vue.use(VueCarousel);
// import Vue from "vue";
/**
* The following block of code may be used to automatically register your
* Vue components. It will recursively scan this directory for the Vue
* components and automatically register them with their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
router,
dayjs,
});
The StatController
Everything is ok here, I'll leave it here just to show you the complete workflow of getting the statistics of reviews and messages of a user
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Musician;
use App\Message;
use App\Review;
use Illuminate\Support\Facades\Auth;
class StatController extends Controller
{
public function showStats(){
// prendo i dati del dottore registrato
$musician = Musician::where('user_id', Auth::id())->first();
// accedo alle tabelle dei messaggi e recensioni per prenderne i dati
$messages = Message::where('musician_id', $musician->id)->get();
$reviews = Review::where('musician_id', $musician->id)->get();
return view('admin.musicians.stats', compact('musician', 'messages', 'reviews'));
}
}
Update you app.blade.php. Remove this <script src="{{ asset('js/app.js') }}"></script> from header and put in body after footer.
...
<script src="{{ asset('js/app.js') }}"></script>
#yield('script')
</body>
</html>
Then use #stack('script') to load other script after app.js, update your My Stat View
#extends('layouts.app')
#section('content')
<div class="my_container">
<h1 class="stat_title">Le tue statistiche</h1>
#if (count($messages) == 0 && count($reviews) == 0)
<h2 id="empty_page">Non hai statistiche disponibili</h2>
#else
<div class="chart_1">
<h4>Numero di messaggi e recensioni ricevute ogni mese</h4>
<canvas id="myChart"></canvas>
</div>
<div class="chart_1">
<h4>Voti ricevuti ogni mese</h4>
<canvas id="myOtherChart"></canvas>
</div>
#endif
<p class="link_dashboard">Torna alla Dashboard</p>
</div>
#endsection
#push('script')
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js" integrity="sha512-Wt1bJGtlnMtGP0dqNFH1xlkLBNpEodaiQ8ZN5JLA5wpc1sUlk/O5uuOMNgvzddzkpvZ9GLyYNa8w2s7rqiTk5Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.10.6/dayjs.min.js" integrity="sha512-bwD3VD/j6ypSSnyjuaURidZksoVx3L1RPvTkleC48SbHCZsemT3VKMD39KknPnH728LLXVMTisESIBOAb5/W0Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>dayjs().format()</script>
<script>
dayjs().format()
var ctx = document.getElementById('myChart');
var ct2 = document.getElementById('myOtherChart');
var commenti = {!! $reviews->toJson() !!};
var messaggi = {!! $messages->toJson() !!};
// console.log(commenti.length);
// console.log(messaggi.length);
var now = dayjs();
if (commenti[0]) {
var primaDataCommento = commenti[0].created_at;
var date1 = dayjs(primaDataCommento);
} else {
var date1 = now;
}
const primaDataMessaggio = messaggi[0].created_at;
const date2 = dayjs(primaDataMessaggio);
var datex;
if (date2 < date1) {
datex = date2;
} else {
datex = date1;
}
var diff = now.diff(datex, 'month');
var diffRece = now.diff(date1, 'month');
var months = [];
var monthsRece = [];
var recensioniMese = [];
var messaggiMese = [];
var voto1 = [];
var voto2 = [];
var voto3 = [];
var voto4 = [];
var voto5 = [];
// prima tabella
var x = 1;
let i = 0;
if (datex.$M == 0) {
diff++;
i++;
x--;
}
for (i; i <= diff; i++) {
var numeroMese = datex.$M + i + x;
months.push(numeroMese + '/2021');
var countRec = 0;
var countMes = 0;
for (let j = 0; j < commenti.length; j++) {
if (numeroMese == dayjs(commenti[j].added_on).$M + 1) {
countRec++;
}
}
for (let j = 0; j < messaggi.length; j++) {
if (numeroMese == dayjs(messaggi[j].added_on).$M + 1) {
countMes++;
}
}
recensioniMese.push(countRec);
messaggiMese.push(countMes);
}
// seconda tabella
x = 1;
i = 0;
if (date1.$M == 0) {
diffRece++;
i++;
x--;
}
for (i; i <= diff; i++) {
var numeroMeseRece = date1.$M + i + x;
monthsRece.push(numeroMeseRece + '/2021');
var countRece1 = 0;
var countRece2 = 0;
var countRece3 = 0;
var countRece4 = 0;
var countRece5 = 0;
for (let j = 0; j < commenti.length; j++) {
if (numeroMeseRece == dayjs(commenti[j].created_at).$M + 1) {
switch (commenti[j].vote) {
case 1:
countRece1++;
break;
case 2:
countRece2++;
break;
case 3:
countRece3++;
break;
case 4:
countRece4++;
break;
case 5:
countRece5++;
break;
default:
break;
}
}
}
voto1.push(countRece1);
voto2.push(countRece2);
voto3.push(countRece3);
voto4.push(countRece4);
voto5.push(countRece5);
}
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: months,
datasets: [
{
label: 'Numero di recensioni',
data: recensioniMese,
backgroundColor: [
'#0000ff8c',
],
borderColor: [
'#0000ff',
],
borderWidth: 1
},
{
label: 'Numero di messaggi ricevuti',
data: messaggiMese,
backgroundColor: [
'#ff00c88c',
],
borderColor: [
'#ff00c8',
],
borderWidth: 1
},
]
},
options: {
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
}
}
});
var myChart = new Chart(ct2, {
type: 'bar',
data: {
labels: monthsRece,
datasets: [
{
label: 'Recensioni con voto 1',
data: voto1,
backgroundColor: [
'#ff00008c',
],
borderColor: [
'red',
],
borderWidth: 1
},
{
label: 'Recensioni con voto 2',
data: voto2,
backgroundColor: [
'#ffa6008c',
],
borderColor: [
'orange',
],
borderWidth: 1
},
{
label: 'Recensioni con voto 3',
data: voto3,
backgroundColor: [
'#ffff008c',
],
borderColor: [
'yellow',
],
borderWidth: 1
},
{
label: 'Recensioni con voto 4',
data: voto4,
backgroundColor: [
'#b7dd298c',
],
borderColor: [
'#b7dd29',
],
borderWidth: 1
},
{
label: 'Recensioni con voto 5',
data: voto5,
backgroundColor: [
'#57e32c8c',
],
borderColor: [
'#57e32c',
],
borderWidth: 1
},
]
},
options: {
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
}
}
});
</script>
#endpush

Click evt is registered to div surrounding checkbox instead of the checkbox itself

I have a list of documents with a checkbox next to each. Clicking on a checkbox is supposed to append that document to a separate div (aka a "Favorites List"). This does not work, but clicking on the div that surrounds the checkbox appends that document correctly. Another issue is that clicking on a checkbox when the Favorites contains one or more documents clears the list.
How can I properly register the checkbox itself to the click event rather than the div surrounding the checkbox? I've tried different methods, such as
$( "input[type='checkbox']" ).on("click", faveFunc), but I've been coming up short so I thought I'd ask about it here.
JS snippet:
import $ from 'jquery';
var tableRes = '';
export default class {
constructor() {
this.loadTableData();
}
// this area contains code that's irrelevant //
// ------ Rendering checkboxes ------- //
$("#km-table-id tbody tr").on("click", function(evt) {
evt.stopPropagation();
if (evt.target.type !== "checkbox") {
$(":checkbox", this).on("click");
}
});
// ------ Appending checkboxes ------- //
let inputType = $("<input />", {"type": "checkbox"})
let chkboxCol = $("#km-table-id tbody tr > td:nth-child(3)");
chkboxCol.append(inputType).addClass("checkbox-class");
// --- My Favorites functionality ---- //
function faveFunc(evt) {
let anchor = $($(evt.target).prev().find("a")[0]).clone();
// let ancTxt = $(anchor).text();
switch($(".populate-faves").find("a:contains(" + $(anchor).text() + ")").length)
{
case 0:
$(".populate-faves").append(anchor);
break;
default:
$(".populate-faves > a:contains(" + $(anchor).text() + ")").remove();
break;
}
};
function newList() {
let data = $(evt.target).prev().find("a").eq(0).html();
let outputList = $(".populate-faves");
$(".populate-faves").html("");
$("#km-table-id tbody tr)").each(function(i, el) {
let cntxFave = $(".add-id", el);
let fave = $(".checkbox-class", el);
let itemText = $(data, el);
if(cntxFave.is(".add-id")) {
outputList.append("<li>" + itemText.html() + "</li>");
}
if(fave.prop("checked")) {
outputList.append("<li>" + itemText.html() + "</li>");
}
});
}; // ------------ newList
$(".checkbox-class").on("click", faveFunc);
HTML snippet:
<div class="col-md-14"> <!-- Right -->
<table id="km-table-id" class="cell-border display stripe-hover">
<thead>
<tr>
<!-- <th></th> -->
<th></th>
<th></th>
<th>Title</th>
<th></th> <!-- Keep here--this is for checkbox col -->
</tr>
</thead>
<tbody></tbody>
</table>
import $ from 'jquery';
import dt from 'datatables.net';
var categories = '';
var tableRes = '';
export default class {
constructor() {
this.loadCategoryData();
this.loadTableData();
}
let KMdocs = {
{
"d": {
"results": [
{
"__metadata": {
"id": "[redacted]",
"uri": "[redacted]",
"etag": "\"2\"",
"type": "[redacted]"
},
"File": {
"__metadata": {
"id": "[redacted]",
"uri": "[redacted]",
"type": "SP.File"
},
"Name": "Guide to Product IDs.docx"
},
"FileLeafRef": "Guide to Product IDs.docx",
"ResourceType": {
"__metadata": {
"type": "Collection(SP.Taxonomy.TaxonomyFieldValue)"
},
"results": [
{
"Label": "Guides \uff06 Protocols",
"TermGuid": "[redacted]",
"WssId": 706
}
]
},
"EncodedAbsUrl": "[redacted]"
},
{
"__metadata": {
"id": "[redacted]",
"uri": "[redacted]",
"etag": "\"3\"",
"type": "SP.Data.KMDocumentsItem"
},
"File": {
"__metadata": {
"id": "[redacted]",
"uri": "[redacted]",
"type": "SP.File"
},
"Name": "LRRP Template 1.docx"
},
"FileLeafRef": "LRRP Template 1.docx",
"ResourceType": {
"__metadata": {
"type": "Collection(SP.Taxonomy.TaxonomyFieldValue)"
},
"results": [
{
"Label": "Templates",
"TermGuid": "[redacted]",
"WssId": 941
},
{
"Label": "Guides \uff06 Protocols",
"TermGuid": "[redacted]",
"WssId": 706
}
]
},
"EncodedAbsUrl": "[redacted]"
},
{
"__metadata": {
"[redacted]",
"uri": "[redacted]",
"etag": "\"3\"",
"type": "SP.Data.KMDocumentsItem"
},
"File": {
"__metadata": {
"id": "[redacted]",
"uri": "[redacted]",
"type": "SP.File"
},
"Name": "LRRP Template 2.docx"
},
"FileLeafRef": "LRRP Template 2.docx",
"ResourceType": {
"__metadata": {
"type": "Collection(SP.Taxonomy.TaxonomyFieldValue)"
},
"results": [
{
"Label": "Templates",
"TermGuid": "[redacted]",
"WssId": 941
},
{
"Label": "Guides \uff06 Protocols",
"TermGuid": "[redacted]",
"WssId": 706
}
]
},
"EncodedAbsUrl": "[redacted]"
}
]
}
}
}
// ------ Loading Category data ------ //
loadCategoryData() {
let res = KMdocs.d.results.filter(function(val) {
return (val.FileLeafRef.trim().length > 0);
}).map(function(obj) {
return {
"FileName": obj.FileLeafRef,
"Titles": obj.File.Name,
"Path": obj.EncodedAbsUrl,
"Categories": obj.ResourceType.results.map(function(val) {
return val.Label;
}).join(";")
};
});
let label = KMdocs.d.results.filter(function(val) {
return (val.FileLeafRef.trim().length > 0);
}).map(function(obj) {
return obj.ResourceType.results.map(function(val) {
return val.Label;
})
});
// ---------- Unique Categs. --------- //
let unique = [];
let temp = KMdocs.d.results.filter(function(val) {
return (val.FileLeafRef.trim().length > 0);
}).forEach(function(obj) {
obj.ResourceType.results.forEach(function(val) {
let divCat = document.createElement("div");
$(divCat).attr("category", encodeURIComponent(val.Label));
$(divCat).html(val.Label);
if (!unique.includes(divCat.outerHTML)) {
unique.push(divCat.outerHTML); // value can be anything, only keys matter
}
})
});
let categories = unique.sort();
$(".indiv-label").append(categories);
} // ------------- loadCategoryData()
// ------ Loading doc title data ----- //
loadTableData() {
// Local icons exist under /SiteAssets/images, if needed //
function docType(fileName) {
let docImg = "<img src='[redacted]/Current.ashx/docx.gif' />"
let msgImg = "<img src='[redacted]/Current.ashx/msg.gif' />"
let nrlImg = "<img src='[redacted]/Current.ashx/nrl.gif' />"
let pdfImg = "<img src='[redacted]/Current.ashx/pdf.gif' />"
let pptImg = "<img src='[redacted]/Current.ashx/pptx.gif' />"
let xlsImg = "<img src='[redacted]/Current.ashx/xls.gif' />"
let docStr = fileName.split(".") // .split() seems to be necessary to render the icons
for (var i = 0; i < docStr.length; i++) {
if (docStr[i].includes('doc')) {
return docStr[i] = docImg;
} // -
else if (docStr[i].includes('DOCX')) {
return docStr[i] = docImg;
} // -
else if (docStr[i].includes('rtf')) {
return docStr[i] = docImg;
} // -
else if (docStr[i].includes('msg')) {
return docStr[i] = msgImg;
} //
else if (docStr[i].includes('nrl')) {
return docStr[i] = nrlImg;
} //
else if (docStr[i].includes('pdf')) {
return docStr[i] = pdfImg;
} //
else if (docStr[i].includes('ppt')) {
return docStr[i] = pptImg;
} // -
else if (docStr[i].includes('PPT')) {
return docStr[i] = pptImg;
} // -
else if (docStr[i].includes('potx')) {
return docStr[i] = pptImg;
} // -
else if (docStr[i].includes('xls')) {
return docStr[i] = xlsImg;
} //
}
} // docType
$.noConflict();
let tableRes = KMdocs.d.results.filter(function(val) {
return (val.FileLeafRef.trim().length > 0);
}).map(function(obj) {
return {
"Path": obj.EncodedAbsUrl,
"Titles": obj.File.Name,
"Categories": obj.ResourceType.results.map(function(val) {
return val.Label;
}).join(";"),
"Blank": "", // use to create an empty column, if necessary
"docImg": docType(obj.File.Name) // Icon
}
})
// --------- Rendering table --------- //
$('#km-table-id').DataTable({
data: tableRes,
columns: [{
data: "Categories"
}, // available but hidden
{
data: "docImg",
sortable: false
}, // hides sorting arrows in icon col
{
data: "Titles"
},
{
data: "Blank",
sortable: false
}
],
columnDefs: [{
data: "Path",
ordering: true,
targets: [2],
render: function(data, type, row) {
return $('<a>')
.attr({
target: "_blank",
href: row.Path
})
.text(data)
.wrap('<div></div>')
.parent()
.html();
},
},
{
searchable: true,
targets: [0],
visible: false
}, // hides Categories col
],
language: {
searchPlaceholder: "Search All Documents"
},
lengthMenu: [10, 25, 50, 100, 250, 500],
order: [],
pageLength: 500, // showing multiple pgs doesn't render all checkboxes...but initially showing all items renders them
paging: true,
pagingType: "full_numbers",
responsive: true,
scrollCollapse: true,
scrollXInner: true,
scrollY: 550,
sDom: '<"top">rt<"bottom"flp><"left">' // affixes dropdown on bottom
});
// ------ Rendering checkboxes ------- //
$("#km-table-id tbody tr").on("click", function(evt) {
evt.stopPropagation();
if (evt.target.type !== "checkbox") {
$(":checkbox", this).on("click");
}
});
// ------ Appending checkboxes ------- //
let inputType = $("<input />", {
"type": "checkbox"
})
let chkboxCol = $("#km-table-id tbody tr > td:nth-child(3)");
chkboxCol.append(inputType).addClass("checkbox-class");
// --- My Favorites functionality ---- //
function faveFunc(evt) {
let anchor = $($(evt.target).prev().find("a")[0]).clone();
switch ($(".populate-faves").find("a:contains(" + $(anchor).text() + ")").length) {
case 0:
$(".populate-faves").append(anchor);
break;
default:
$(".populate-faves > a:contains(" + $(anchor).text() + ")").remove();
break;
}
};
function newList() {
let data = $(evt.target).prev().find("a").eq(0).html();
let outputList = $(".populate-faves");
$(".populate-faves").html("");
$("#km-table-id tbody tr)").each(function(i, el) {
let cntxFave = $(".add-id", el);
let fave = $(".checkbox-class", el);
let itemText = $(data, el);
if (cntxFave.is(".add-id")) {
outputList.append("<li>" + itemText.html() + "</li>");
}
if (fave.prop("checked")) {
outputList.append("<li>" + itemText.html() + "</li>");
}
});
}; // ------------ newList
$(":checkbox").on("click", faveFunc);
$("#add-id").on("click", faveFunc); // does not work
// Linking custom search w/ DT search //
let oTable = $("#km-table-id").DataTable();
$("#searchbar").on("input", function() {
oTable.search($(this)
.val() + " " + decodeURIComponent($(this)
.attr("category"))).draw();
})
} // ------------------ loadTableData
} // ------------- export default class
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1, shrink-to-fit=no">
<title>Pages - KM</title>
<meta name="description" content="description here">
<meta name="keywords" content="keywords,here">
<!-- DataTables CSS -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.2.7/css/select.dataTables.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/fixedheader/3.1.5/css/fixedHeader.dataTables.min.css">
<link rel="stylesheet" href="KMStyles.css" type="text/css">
<!-- jQuery first, then Popper.js -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<!------------------------------->
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js" defer></script>
<script type="text/javascript" src="https://cdn.datatables.net/select/1.2.7/js/dataTables.select.min.js"></script>
<!------------------------------->
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.2/core.min.js"></script>
<script type="text/javascript" src="SiteAssets/scripts/getListItems.js"></script>
</head>
<body>
<script src="./bundle.js"></script>
<div class="km-div-container">
<div class="col-md-3">
<!-- Left -->
<span class="KM-title"><h1>KM</h1></span>
<div class="form-group">
<input category="" class="form-control" daysprior="" id="searchbar" input-all="" placeholder="Search All Documents..." type="search">
</div>
<div id="myFave.hs-gc-header" class="faves-div">
<p style="font-weight:bold">My Favorites:</p>
<div class="populate-faves"></div>
<!-- location of favorited documents -->
</div>
</div>
<!-------------------------------------------->
<div class="col-md-3" id="middle-id">
<!-- Middle -->
<p>
<div class="all-docs-title" category="" style="font-weight:bold; cursor:pointer" input="">All Documents</div>
</p>
<p>
<div class="recently-added-title" category="" days="30" style="cursor:pointer;">Recently Added and/or Modified</div>
</p>
<div id="km-labels">
<a>
<p class="indiv-label" style="cursor:pointer;"></p>
</div>
</div>
<!-------------------------------------------->
<div class="col-md-14">
<!-- Right -->
<table id="km-table-id" class="cell-border display stripe-hover">
<thead>
<tr>
<!-- <th></th> -->
<th></th>
<th></th>
<th>Title</th>
<th></th>
<!-- Keep here--this is for checkbox col -->
</tr>
</thead>
<tbody></tbody>
</table>
<!-- <ul class="custom-menu">
<li data-action="open" id="open-id">Open Document</li>
<li data-action="add" id="add-id">Set As Favorite</li>
<li data-action="email">Email Document</a></li>
</ul> -->
</div>
<!-- col-md-14 -->
<!-- <div class="kmdialog"></div> -->
<!-- what is this? -->
</div>
<!-- km-div-container -->
</body>
</html>
The core of the demo is the following:
event.type ⇩ Event Handler ⇩
$(document).on('change', 'CHECKBOX', addFav);
⇧ event.currentTarget ⇧ event.target
Demo Outline
Assign each checkbox a data-* attribute with a unique value. ex. data-id="1"
To reference and clone an element in a table cell placed before the table cell with the checkbox, ex.:
$(event.target).closest('td').prev('td').find(ANCHOR).clone();
Use the data-* attribute of the checkbox to associate it with the cloned element in the example below the cloned anchor is appended to a <li>, ex.:
$(LI).addClass('fav'+ID).append(ANCHOR);
The association is used to remove the <li> from the favorites list when the checkbox is unchecked, ex.:
$('.fav'+ID).remove();
Review demo in full page mode
<!DOCTYPE html>
<html>
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.css" rel="stylesheet">
<style>
caption {
caption-side: top;
font-size: 1.5rem;
font-weight: 400
}
.favorite {
list-style: none
}
.favorite li::before {
content: '\1f49a\a0\a0'
}
</style>
</head>
<body>
<header class="container">
<section class='row'>
<fieldset class="col-md-12">
<legend>💖 Favorites:</legend>
<ul class='favorite'></ul>
</fieldset>
</section>
</header>
<hr>
<main class='container'>
<section class='row'>
<article class="col-md-12">
<table class='table'>
<caption>Data</caption>
<thead>
<tr>
<th></th>
<th>Link</th>
<th>Title</th>
<th></th>
</tr>
</thead>
<tbody class='table-bordered'>
<tr>
<td></td>
<td>
<a href='#/' class='lnx'>LINK 1: Category I</a></td>
<td>
<label class="custom-control custom-checkbox">
<input class="chx custom-control-input" type="checkbox" data-id='1'>
<b class="custom-control-indicator"></b>
<b class="custom-control-description"> 💙</b>
</label>
</td>
<td></td>
</tr>
<tr>
<td></td>
<td>
<a href='#/' class='lnx'>LINK 2: Category II</a></td>
<td>
<label class="custom-control custom-checkbox">
<input class="chx custom-control-input" type="checkbox" data-id='2'>
<b class="custom-control-indicator"></b>
<b class="custom-control-description"> 💙</b>
</label>
</td>
<td></td>
</tr>
<tr>
<td></td>
<td>
<a href='#/' class='lnx'>LINK 3: Category III</a></td>
<td>
<label class="custom-control custom-checkbox">
<input class="chx custom-control-input" type="checkbox" data-id='3'>
<b class="custom-control-indicator"></b>
<b class="custom-control-description"> 💙</b>
</label>
</td>
<td></td>
</tr>
</tbody>
</table>
</article>
</section>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).on('change', '.chx', addFav);
function addFav(e) {
var tgt = e.target;
var ID = $(tgt).data('id');
if (tgt.checked) {
var lnx = $(tgt).closest('td').prev('td').find('.lnx').clone();
var item = document.createElement('li');
$('.favorite').append(item);
$(item).addClass('fav' + ID).append(lnx);
return false;
} else if (!tgt.checked) {
$('.fav' + ID).remove();
}
}
</script>
</body>
</html>

AngularJS: How to count filters items

In my example jsfidle you can see my doubt.
My jsfiddle
How do I get it to count the number of it and only appears to me once and not repeatedly.
My Html:
<section class="left" style="border-right:1px">
<div class="filter">
Pant Size
<div>
<div ng-repeat="professionalarea in pantsGroup">
<b><input type="checkbox" ng-model="usePants[professionalarea.description]"/>{{professionalarea.description}}</b>
<span>({{(filteredPlayers | filter:professionalarea).length}})</span>
</div>
</div>
</div>
</section>
My controller
$scope.$watch(function () {
return {
players: $scope.players,
usePants: $scope.usePants
}
}, function (value) {
var selected;
//here i want call professionalarea.description and don't pants
$scope.pantsGroup = uniqueItems($scope.players, 'professionalarea');
var filterAfterPants = [];
selected = false;
for (var j in $scope.players) {
var p = $scope.players[j];
for (var i in $scope.usePants) {
if ($scope.usePants[i]) {
selected = true;
if (i == p.professionalarea.description) {
filterAfterPants.push(p);
break;
}
}
}
}
if (!selected) {
filterAfterPants = $scope.players;
}
$scope.filteredPlayers = filterAfterPants;
}, true);
Example Image
Image
Added new function to get distinct items i.e. getDistinctValue
Please find following snippet..
(function () {
'use strict';
var myApp = angular.module('myApp', []);
var uniqueItems = function (data, key) {
var result = new Array();
for (var i = 0; i < data.length; i++) {
var value = data[i][key];
console.log(value);
if (result.indexOf(value) == -1) {
result.push(value);
}
}
return result;
};
function getDistinctValue(items) {
var lookup = {};
var result = [];
for (var item, i = 0; item = items[i++];) {
var name = item.professionalarea.description;
if (!(name in lookup)) {
lookup[name] = 1;
result.push(name);
}
}
return result;
}
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function (file, uploadUrl) {
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
})
.success(function () {
})
.error(function () {
});
}
}]);
myApp.controller('myCtrl', ['$scope', function ($scope) {
$scope.usePants = {};
$scope.players = [
{
name: 'Bruce Wayne',
shirt: 'XXL',
pants: '42',
professionalarea: {
idAreaProfissional: 1,
description: "IT"
},
shoes: '12'
}, {
name: 'Bruce Wayne',
shirt: 'XXL',
pants: '28',
professionalarea: {
idAreaProfissional: 1,
description: "test"
},
shoes: '12'
}, {
name: 'Bruce Wayne',
shirt: 'XXL',
pants: '35',
professionalarea: {
idAreaProfissional: 1,
description: "IT"
},
shoes: '12'
}
];
// Watch the pants that are selected
$scope.$watch(function () {
return {
players: $scope.players,
usePants: $scope.usePants
}
}, function (value) {
var selected;
//here i want call professionalarea.description and don't pants
$scope.pantsGroup = getDistinctValue($scope.players);
var filterAfterPants = [];
selected = false;
for (var j in $scope.players) {
var p = $scope.players[j];
for (var i in $scope.usePants) {
if ($scope.usePants[i]) {
selected = true;
if (i == p.professionalarea.description) {
filterAfterPants.push(p);
break;
}
}
}
}
if (!selected) {
filterAfterPants = $scope.players;
}
$scope.filteredPlayers = filterAfterPants;
}, true);
$scope.$watch('filtered', function (newValue) {
if (angular.isArray(newValue)) {
console.log(newValue.length);
}
}, true);
}]);
myApp.filter('groupBy',
function () {
return function (collection, key) {
if (collection === null) return;
return uniqueItems(collection, key);
};
});
})();
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="app.js" type="text/javascript"></script>
<style>
.gridStyle {
border: 1px solid rgb(212, 212, 212);
margin-left: 15px;
width: 97%;
height: 130px;
float: left;
font-weight: normal;
padding: 35px 10px 10px 10px;
}
</style>
<title>Upload </title>
</head>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<div>
<section class="left" style="border-right:1px">
<div class="filter">
Pant Size
<div>
<div ng-repeat="professionalarea in pantsGroup">
<b><input type="checkbox" ng-model="usePants[professionalarea]" />{{professionalarea}}</b>
<span>({{filteredPlayers.length}})</span>
</div>
</div>
</div>
</section>
<section class="right" style="border-right:1px">
<div>
<ul>
<li ng-repeat="player in filteredPlayers | filter:query">
<p><b>Player: {{player.name}}</b></p>
<p>Shirt Size: {{player.shirt}} Pant Size: {{player.pants}} Shoe Size: {{player.shoes}}</p>
</li>
</ul>
</div>
</section>
</div>
</div>
</body>
</html>

Angularjs, filter array by array

Now, I have tow buttons. The first button named "array1", the other button named 'array2'. I have an array called "newArray." I have an array named "array1". I have an array named "array2".I have an array called "unselectedArray."
When I click the array1 button, I want to show the item in array1, but the item is not in "newArray1". When I click the array2 button, I want to show the item in array2, but the item is not in "newArray1" This show array is "unselectedArray."
When I click the item in the "unselectedArray," the item is added in 'newArrray';
I use two hours to solve it, but I haven't written the right code.
This is my code:
<style>
.bigDiv {
width: 500px; height: 100%;
margin: 60px auto; background-color: red;
}
li {
float: left;
width: 50px; height: 50px;
}
.selected,.buttonArea,.unselected {
height: 100px;
}
</style>
<div class="bigDiv">
<div class="selected">
<ul>
<li ng-repeat="item in newArray">
{{item.text}}
</li>
</ul>
</div>
<div class="buttonArea">
<button ng-click="showArrayFun('array1')">array1</button>
<button ng-click="showArrayFun('array2')">array2</button>
</div>
<div class="unselected">
<ul>
<li ng-click="addToNewArrayFun($index)" ng-repeat="item in unselectedArray">
{{item.text}}
</li>
</ul>
</div>
</div>
angular.module('myApp', []).controller('con', function ($scope) {
$scope.array1 = [
{
id: 11,
text: 'one'
},
{
id: 12,
text: 'two'
},
];
$scope.array2 = [
{
id: 21,
text: 'winter'
},
{
id: 22,
text: 'spring'
},
];
$scope.newArray = [
{
id: 12,
text: 'two'
}
];
$scope.unselectedArray = [];
$scope.addToNewArrayFun = function (index) {
$scope.newArray.push($scope.unselectedArray[index]);
};
$scope.showArrayFun = function (arrayName) {
if (arrayName == 'array1') {
$scope.unselectedArray = $scope.array1.filter(function (item) {
console.log(($scope.newArray.indexOf(item) == -1));
return ( ($scope.newArray.indexOf(item) == -1) == true );
});
} else if (arrayName == 'array2') {
$scope.unselectedArray = $scope.array2.filter(function (item) {
console.log(($scope.newArray.indexOf(item) == -1));
return ( ($scope.newArray.indexOf(item) == -1) == true );
});
}
}
}
);
Why my code not work? Who can correct my code?
Please write the code which is using $filter.
Who can create AngularJS custom filters to realize it.
// Code goes here
angular.module('myApp', []).controller('con', function ($scope) {
$scope.array1 = [
{
id: 11,
text: 'one'
},
{
id: 12,
text: 'two'
},
];
$scope.array2 = [
{
id: 21,
text: 'winter'
},
{
id: 22,
text: 'spring'
},
];
$scope.newArray = [
{
id: 12,
text: 'two'
}
];
$scope.unselectedArray = [];
$scope.addToNewArrayFun = function (index) {
$scope.newArray.push($scope.unselectedArray[index]);
$scope.unselectedArray.splice(index, 1);
};
$scope.showArrayFun = function (arrayName) {
if (arrayName == 'array1') {
$scope.unselectedArray = $scope.array1.filter(function (item) {
return ( ($scope.newArray.indexOf(item) == -1));
});
} else if (arrayName == 'array2') {
$scope.unselectedArray = $scope.array2.filter(function (item) {
return ( ($scope.newArray.indexOf(item) == -1));
});
}
};
})
/* Styles go here */
.bigDiv {
width: 500px; height: 100%;
margin: 60px auto;
background-color: red;
}
li {
float: left;
width: 50px; height: 50px;
}
.selected,.buttonArea,.unselected {
height: 100px;
}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="script.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body ng-controller="con">
<div class="bigDiv">
<div class="selected">
<ul>
<li ng-repeat="item in newArray">
{{item.text}}
</li>
</ul>
</div>
<div class="buttonArea">
<button ng-click="showArrayFun('array1')">array1</button>
<button ng-click="showArrayFun('array2')">array2</button>
</div>
<div class="unselected">
<ul>
<li ng-click="addToNewArrayFun($index)" ng-repeat="item in unselectedArray">
{{item.text}}
</li>
</ul>
</div>
</div>
</body>
</html>
<div class="bigDiv">
<div class="selected">
<ul>
<li ng-click=" deleteItemFun($index)" ng-repeat="item in newArray track by $index ">
{{item.text}}
</li>
</ul>
</div>
<div class="buttonArea">
<button ng-click="showArrayFun('array1')">array1</button>
<button ng-click="showArrayFun('array2')">array2</button>
</div>
<div class="unselected">
<ul>
<li ng-click="addToNewArrayFun($index)" ng-repeat="item in unselectedArray | fiArray : newArray ">
{{item.text}}
</li>
</ul>
</div>
</div>
angular.module('myApp', []).filter('fiArray', function () {
return function (array, aimArray) {
var tempArray = array;
if (tempArray.length == 0)
return [];
for (var i = 0; i < aimArray.length; i++) {
for (var j = 0; j < tempArray.length; j++) {
if (tempArray[j].id === aimArray[i].id) {
tempArray.splice(j, 1);
j--;
break;
}
}
}
return tempArray;
}
})
.controller('con', ['$scope', 'fiArrayFilter', function ($scope, fiArrayFilter) {
$scope.newArray = [
{
id: 12,
text: 'two'
}
];
$scope.array1 = [
{
id: 11,
text: 'one'
},
{
id: 12,
text: 'two'
},
];
$scope.array2 = [
{
id: 21,
text: 'winter'
},
{
id: 22,
text: 'spring'
},
];
$scope.unselectedArray = [];
$scope.addToNewArrayFun = function (index) {
$scope.newArray.push($scope.unselectedArray[index]);
};
$scope.deleteItemFun = function (index) {
$scope.newArray.splice(index, 1)
}
$scope.showArrayFun = function (arrayName) {
var copyArr = [];
if (arrayName == 'array1') {
copyArr = $scope.array1.concat();
}
else if (arrayName == 'array2') {
copyArr = $scope.array2.concat();
}
$scope.unselectedArray = copyArr;
}
}])
;

How to Filter data using date in angular js?

I have list of student names & i want to filter names using two dates.
I have two date pickers one is for from date another one is for to date .if user select 2015-10-19 as from date and 2015-10-20 as to date , then name list should show between this two dates.
example user selected above dates
list should be
Ramesh
Vignesh
Sarath
Gomal
I have added my code below some one can help me out .
<!--begin snippet: js hide: false -->
<!--language: lang-js -->
angular.module("date", [])
.directive("datepicker", function () {
return {
restrict: "A",
link: function (scope, el, attr) {
el.datepicker({
dateFormat: 'yy-mm-dd'
});
}
};
})
.directive("datepicker1", function () {
return {
restrict: "A",
link: function (scope, el, attr) {
el.datepicker({
dateFormat: 'yy-mm-dd'
});
}
};
})
.controller("dateCtrl", function ($scope) {
$scope.names= [{
id: "1",
C_Name: "Ramesh",
C_Phone: "*******",
C_Option: {
"date": {
"$date": "2015-10-19T09:52:26.507Z"
}
}
}, {
id: "2",
C_Name: "Suresh",
C_Phone: "*****",
C_Option: {
"date": {
"$date": "2015-10-21T09:52:26.507Z"
}
}
}, {
id: "3",
C_Name: "Vignesh",
C_Phone: "*******",
C_Option: {
"date": {
"$date": "2015-10-20T09:52:26.507Z"
}
}
},
{
id: "4",
C_Name: "Sarath",
C_Phone: "******",
C_Option: {
"date": {
"$date": "2015-10-20T09:52:26.507Z"
}
}
},
{
id: "5",
C_Name: "Sundhar",
C_Phone: "******",
C_Option: {
"date": {
"$date": "2015-10-21T09:52:26.507Z"
}
}
},
{
id: "6",
C_Name: "Rajesh",
C_Phone: "******",
C_Option: {
"date": {
"$date": "2015-10-18T09:52:26.507Z"
}
}
},
{
id: "7",
C_Name: "Gomal",
C_Phone: "******",
C_Option: {
"date": {
"$date": "2015-10-20T09:52:26.507Z"
}
}
}
]
});
<!-- language: lang-html -->
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.min.css" rel="stylesheet" type="text/css" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
<div ng-app="date">
<div ng-controller="dateCtrl">
<!-- jq -->
<!-- ng -->
From Date:<input type="text" datepicker ng-model="date2" />
<span>{{date2}}</span>
To Date:<input type="text" datepicker1 ng-model="date3" />
<span>{{date3}}</span>
<br><br><br>
<label>List Of Names</label>
<br>
<div ng-repeat="name in names | filter:search" >
<br>{{name.C_Name}}
<br>
</div>
</div>
</div>
<!-- end snippet -->
demo # JSFiddle
Working Fiddle:
Change in HTML:
<div ng-repeat="name in names | myfilter:date2:date3" >
Change in JavaScript: Add following custom filter
moduleName.filter("myfilter", function() {
return function(items, from, to) {
var arrayToReturn = [];
for (var i=0; i<items.length; i++){
var test = new Date(items[i].C_Option.date.$date);
var month = test.getMonth()+1;
var date = test.getDate();
var year = test.getFullYear();
var newDate = year+"-"+month+"-"+date
if (newDate>= from && newDate <= to) {
arrayToReturn.push(items[i]);
}
}
return arrayToReturn;
};
})
Source: https://stackoverflow.com/a/25521779/3186722
You need to create a custom filter function for this functionality and compare the date on the records against the start and end date entered by user.
Im using moment.js for date comparisions as it the best library for date comparisions.
HTML CODE:
<div ng-repeat="name in names | filter: dateRangeFilter('C_Option', date2, date3)">
<br>{{name.C_Name}}
<br>
</div>
<span>{{resultsCount}} records returned</span>
JQUERY CODE:
$scope.dateRangeFilter = function(property, startDate, endDate) {
return function(item) {
$scope.resultsCount = 0;
if (item[property] === null){
return false;
}
var localEndDate ='';
if(typeof endDate === 'undefined' ){
localEndDate = moment(new Date(),"DD-MM-YYYY") +'T23:59:59.000Z';
}else{
localEndDate = endDate + 'T23:59:59.000Z';
}
var currentDate = moment(item[property].date.$date, "DD-MM-YYYY");
var s = moment(startDate, "DD-MM-YYYY");
var e = moment(localEndDate, "DD-MM-YYYY");
if (currentDate >= s && currentDate <= e) {
$scope.resultsCount++;
return true;
}
return false;
}
}
Live Demo # JSFiddle
Update : code updated to show the count of records after filter.
var nameSpace = angular.module('tst',[]);
nameSpace.controller('MyController', function MyController($scope) {
$scope.date1 = "27-05-2010"
$scope.date2 = "29-07-2015";
$scope.orders = [
{
"date1": 1306487800,
"date2": 1406587800
},
{
"date1": 1196487800,
"date2": 1406597800
}]
});
// parse a date in dd-mm-yyyy format
function parseDate(input) {
var parts = input.split('-');
// Note: months are 0-based
return new Date(parts[2], parts[1]-1, parts[0]);
}
nameSpace.filter("myfilter", function() {
return function(items, from, to) {
var df = parseDate(from);
var dt = parseDate(to);
var arrayToReturn = [];
for (var i=0; i<items.length; i++){
var tf = new Date(items[i].date1 * 1000),
tt = new Date(items[i].date2 * 1000);
if (tf > df && tt < dt) {
arrayToReturn.push(items[i]);
}
}
return arrayToReturn;
};
});
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.min.css" rel="stylesheet" type="text/css" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
<div ng-app="tst">
<div ng-controller="MyController">
<table>
<tr>
<td>From:<input ng-model="date1" type="text" placeholder="" /></td>
<td>To:<input ng-model="date2" type="text" placeholder="" /></td>
</tr>
<tr ng-repeat="order in orders | myfilter:date1:date2">
<td>{{order.date1 * 1000 | date:'dd-MM-yyyy'}}</td>
<td>{{order.date2 * 1000 | date:'dd-MM-yyyy'}}</td>
</tr>
</table>
</div>
</div>

Categories