ng-repeat not displaying data from localStorage - angularjs

In my Controller:
By clicking on an element, the information is given to tabNameStore.
The data is displayed in html by name
$scope.openTab = function($event){
//Checks for doubles
if($scope.tabNameStore.length>0){
for(var i=0; i<$scope.tabNameStore.length; i++){
if($scope.tabNameStore[i].id == $event.currentTarget.id){
console.log("Already open");
return;
}
}
}
//Saves name, ID and number
$scope.tabNameStore[count] = ({name: $event.currentTarget.innerHTML,
id: $event.currentTarget.id, num: count++});
//Tries to get item by id
var local = localStorage.getItem($event.currentTarget.id);
//If not stored in local, it does so
if (local == null){
localStorage.setItem($event.currentTarget.innerHTML,
$scope.tabNameStore[count-1].name);
localStorage.setItem($event.currentTarget.id,
$scope.tabNameStore[count-1].id);
console.log("null");
} else{
console.log("not null");
return;
}
}
Save the data from localStorage back in tabNameStore
$window.onload = function() {
var archive = [];
archive = allStorage();
count = 0;
for(var i=0; i<archive.length/2; i++){
if(archive[i] != null){
$scope.tabNameStore[count] = ({name: archive[i], id:
archive[i+archive.length/2], num: count++});
}
}
}
Getting all data from localStorage
function allStorage() {
var keys = Object.keys(localStorage); // Gibt alle Schlüssel zurück
var archive = [];
for (var i=0; i< keys.length; i++) {
archive.push(keys[i]);
}
return archive;
}
The HTML is:
<article id="default">
<div id="heading">
<a href="###" class="tab" id="desktop" >Desktop</a>
<a href="###" class="tab" id="" data-ng-repeat="y in
tabNameStore" data-ng-click="" >{{y.name}}</a>
</div>
<div class="gridly toggle" id="Desktop">
<div class="brick small" draggable="true" data-letters="
{{x.name[0]}}" id="{{x.id}}" data-ng-repeat="x in storage |
orderBy: '-name'" data-ng-click="openTab($event)">
{{x.name}}
</div>
</div>
</article>
After reloading the page and getting the data from localStorage it's still not displayed, even if the array is filled. Just if I click again on one of my elements (openTab function), all elements stored in localStorage are displayed at once.

I solved it:
By adding a $scope.$apply around the part that reloads the array:
....
$scope.$apply(function(){
for(var i=0; i<archive.length/2; i++){
if(archive[i] != null){
$scope.tabNameStore[count] = ({name: archive[i], id:
archive[i+archive.length/2], num: count++});
}
}
});
....
Like this the updated array is set up for angularjs after reloading.

Related

push object to array of arrays vue re-rendering failing

I have this weird issue where I can't seem to push an object to an array of arrays.
I am able to log the value of groups....but I can't update it.
here's my function to push to the groups array under a given set of conditions
calcExclusion: function(){
this.hideExclusionGroups = true //hides the exclusion groups from app before calculations
for(var i = 0; i < this.exclusionGroups.length; i++){
if(this.numberOfGroups < this.exclusionGroups.length){
alert('could not calculate, there are more exclusion groups than groups')
return
}
for(var j = 0; j < this.exclusionGroups[i].students.length; j++){
if(this.exclusionGroups[i].students.length == 1){
alert ('could not calculate, groups must be bigger than 1')
return
}
//console.log('group number', g,'student to add',this.exclusionGroups[i].students[j])
if(j < this.numberOfGroups){
this.groups[i].push(this.exclusionGroups[i].students[j].first_name)
console.log(this.groups[i])
}
}
}
},
here is where I render the data
<div v-for="(group, index) in groups" class="d-inline-block bg-white p-2 m-2 border rounded">
<span>Group {{ index + 1 }}</span>
<ul>
<li class="groupItems" v-for="student in group">
{{ student.first_name }}
<input type="hidden" :name="'group['+index+']'" :value="student.id">
</li>
</ul>
</div>
I am able to edit 'groups' to some extent but groups is referencing the computed prop here
computed: {
groups: function () {
if(! Number.isInteger(this.numberOfGroups)) {
console.log('mal');
return [];
}
const array = [];
for (let j = 0; j < this.numberOfGroups; j++) {
array[j] = [];
}
let i = 0;
this.students.forEach((student) => {
const x = i % this.numberOfGroups;
if(student.include === false){
array[x].push(student);
}
i++;
});
return array;
},
},
You are updating the results of a computed property. The result is not reactive, that's why you see that your code is updating the groups array, but you don't see any changed in the DOM.
You need to move the logic from calcExclusion inside the computed method for groups.

Search a city using google map

I'm using a google map to show location in find search box (from that link) which is working fine:
angular.module('ui.bootstrap.demo').controller('TypeaheadCtrl',function($scope, $http) {
$scope.getLocation = function(val) {
return $http.get('//maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}).then(function(response){
return response.data.results.map(function(item){
return item.formatted_address;
});
});
};
<h4>Asynchronous results</h4>
<pre>Model: {{asyncSelected | json}}</pre>
<input type="text" ng-model="asyncSelected" placeholder="Locations loaded via $http" uib-typeahead="address for address in getLocation($viewValue)" typeahead-loading="loadingLocations" typeahead-no-results="noResults" class="form-control">
<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh"></i>
<div ng-show="noResults">
<i class="glyphicon glyphicon-remove"></i> No Results Found
</div>
I would like to know if possible to show my custom city near the search entry ?
Let's say I have bbCity, aaCity, ccCity and when a user types bb, her/him gets the nearest one (bbCity).
Thanks
I don't know if it's a right way but I solved it by adding the answer from this link.
angular.module('ui.bootstrap.demo').controller('TypeaheadCtrl',function($scope, $http) {
// Predefined areas
var predefinedLocations = [[48,68435270497298,4,39454410970211, 'city 1'],[48,33375503137806,5,616522543132305, 'city 2']];
$scope.getLocation = function(val) {
return $http.get('//maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}).then(function(response){
return response.data.results.map(function(item){
// Hold distances
var distances = [];
var start = new google.maps.LatLng(item.geometry.location.lat, item.geometry.location.lng);
for (var i = 0; i < predefinedLocations.length; i++)
{
var point = new google.maps.LatLng(predefinedLocations[i][0],predefinedLocations[i][1]);
var distance = google.maps.geometry.spherical.computeDistanceBetween(start, point);
distances.push(distance);
}
var firstElement = distances[0];
var index = 0;
for (var i = 1; i < distances.length; i++)
{
if(distances[i] < firstElement)
{
firstElement = distances[i];
index = i;
}
}
return predefinedLocations[index][2];
});
});
};

AngularJS: groups of checkboxes inside a loop

There are some categories inside ng-repeat, and each one includes some accounts, If each category is selected then all accounts inside it must be selected and vice versa. Also, if one account is not selected, then the parent category is not selected.
How can I do that?
Here is how the view is:
And the code fiddle:
http://jsfiddle.net/2f6qscrp/208/
Thank you for any help.
Here is the working fiddle for your case,
http://jsfiddle.net/balasuar/2f6qscrp/209/
HTML
<div ng-app='home'>
<!-- App goes here -->
<md-content layout-padding ng-controller="MainCtrl as mainCtrl">
<md-checkbox ng-model="selectedAll"
ng-change="toggleAll()"
class="md-primary">
<span ng-if="selectedAll">Un-</span>Select All
</md-checkbox>
<div ng-repeat="category in naturalAccounts">
<md-checkbox class="md-primary" ng-model="category.selected" ng-change="toggleCategory(category)">
{{ category.name }}
</md-checkbox>
<div ng-repeat="acc in category.accounts">
<md-checkbox class="md-primary" ng-model="acc.selected" ng-change="toggleAccount(category, acc)" >{{acc.name}}</md-checkbox>
</div>
</div>
</md-content>
</div>
JS
angular.module('home', ['ngAria', 'ngAnimate', 'ngMaterial']);
angular.module('home').config(function ($mdThemingProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('pink')
.accentPalette('grey');
});
angular.module('home').controller('MainCtrl', function ($scope) {
$scope.naturalAccounts = [
{"id":0,"name":"category0","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] },
{"id":1,"name":"category1","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] },
{"id":2,"name":"category2","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] }
];
$scope.selectedAll = false;
function setSelectedAll() {
for(var i = 0; i < $scope.naturalAccounts.length; i++) {
var category = $scope.naturalAccounts[i];
$scope.selectedAll = category.selected;
if(!$scope.selectedAll) {
break;
}
}
}
$scope.toggleAll = function() {
for(var i = 0; i < $scope.naturalAccounts.length; i++) {
var category = $scope.naturalAccounts[i];
category.selected = $scope.selectedAll;
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
account.selected = $scope.selectedAll;
}
}
};
$scope.toggleCategory = function(category) {
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
account.selected = category.selected;
}
setSelectedAll();
};
$scope.toggleAccount = function(category, account) {
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
category.selected = account.selected;
if(!category.selected) {
break;
}
}
setSelectedAll();
};
});
<input type="checkbox" ng-model="category.checked" ng-change="checkAllAccountsOfCategoryIfChecked(category)" />
and
<input type="checkbox" ng-model="account.checked" ng-change="checkOrUncheckCategoryBasedOnItsAccounts(category)" />
In your controller:
$scope.checkAllAccountsOfCategoryIfChecked = function(category) {
// TODO if category is checked, then loop over all its accounts and check them
}
$scope.checkOrUncheckParentCategory = function(category) {
// TODO if all the category's accounts are checked,
// then check the category, otherwise uncheck it
}

How can I dynamically limit data showing in an ng-repeat?

I have this ng-repeat that I show split over three rows here for clarity:
ng-repeat="row in phs.phrasesView =
(phs.phrases | orderBy:phs.phrasesOrderBy[phs.phrasesOrderById]
.key:phs.phrasesSortDirectionId == 1)">
On my form I have a field phs.keywordRange
Is there a way that I can make it so the rows returned are filtered as follows:
When phs.keywordRange is null or empty string, all rows are shown
When phs.keywordRange is A then only rows where row.keyword starts with A are shown
When phs.keywordRange is ABC then only rows where row.keyword starts with ABC are shown
Make your own filter, like this fiddle.
Changing the $scope.keywordRange will update the list accordingly.
as shortcut:
.filter('keywordRange', function() {
return function(value, keyword) {
var out = [];
if(!keyword) {
return value;
}
for(var i = 0; i < value.length; i++) {
if(value[i].startsWith(keyword)){
out.push(value[i]);
}
}
return out;
};
});
function MyCtrl($scope) {
$scope.keywordRange = 'ti';
$scope.lines = [
'rest1', 'rest2', 'tiago', 'pedro', 'america'
];
}
and the html
<div ng-controller="MyCtrl">
<div ng-repeat="line in lines | keywordRange:keywordRange">
<p>{{line}}</p>
</div>
</div>

Can't find Element Inside Template with querySelectorAll

Im done with visual things of my proj. Now, trying to put template tags. But my 'click toggle' event isnt working now. Tried lots of solutions. At the same time you may give hints about polymer.
Putted template tags like this:
<template is="dom-if" if="{{isUnis(tabSelected)}}">
<template is="dom-repeat" items="{{unis}}">
<paper-icon-item u="{{item.name}}">
<iron-image src="{{unImg(item.name)}}" sizing="contain" style="width:32px;height:32px" item-icon fade preload></iron-image>
<div class="flex">{{item.name}}</div>
<span>1</span>
</paper-icon-item>
</template>
</template>
<template is="dom-if" if="{{isDers(tabSelected)}}">
<paper-icon-item u="İstanbul">
<iron-image src="/unis/uni/istanbul.png" sizing="contain" style="width:32px;height:32px" item-icon fade preload></iron-image>
<div class="flex">İstanbul</div>
<span>1</span>
</paper-icon-item>
</template>
And my script inside template:
var notarApp = Polymer.dom(document).querySelector('notar-app');
document.addEventListener('polymer-ready', function() {
var p = Polymer.dom(notarApp.root).querySelectorAll('paper-icon-item'),
sifir = 0,
buyuttu = document.getElementById('#buyuttu'),
selected = document.getElementById('#selected');
for (var i = 0; i < p.length; i++) {
p[i].addEventListener('click', function() {
this.classList.toggle('shadow-2');
var listme = [];
for (var j = 0; j < p.length; j++) {
if (!(hasClass(p[j], 'shadow-2'))) {
continue;
}
listme.push(" " + p[j].attributes[0].nodeValue);
selected.innerHTML = listme;
}
if (listme.length == 0) {
selected.innerHTML = 'Listelemek için üniversite ve/ya ders seçin';
}
if (sifir == 0 && listme.length > 4) {
buyuttu.show();
sifir++;
}
});
}
});
Last i tried this inside polymer-ready and nothing happened:
if(p.length) {
console.log(p);
}
My guess is dom-if doesnt load content when if state is false.

Resources