tabset prevents table update - angularjs

I have a working table with a filter:
http://plnkr.co/edit/WnV7OUplcLHVOKbeTrSw?p=preview
After wrapping it in a tabset it stops working (the filter is still updated):
http://plnkr.co/edit/8uw2UhSC59txms5X563L?p=preview
But it worked with old versions before I updated:
http://plnkr.co/edit/eJvYtpc3efkydsQy8caL?p=preview
(angular 1.0.8 + bootstrap 2.0.3 + angular-ui-bootstrap-0.6.0)
Why did it stop working after the update?

http://plnkr.co/edit/70sLuA4gltgxhwTE0XT1
HTML (Just modified the filter usage)
<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="TabsDemoCtrl">
<tabset>
<tab heading="broken filter">
<form class="form-inline" role="form">
<select id="okFilterbox" ng-model="okFilterBool">
<option>nothing</option>
<option>all</option>
</select>
</form>
<p>{{okFilterBool}}</p>
<div>
<table>
<tr ng-repeat="item in items | filterItem:okFilterBool">
<td>{{item.name}}</td>
</tr>
</table>
</div>
</tab>
<tab heading="tab2">
</tab>
</div>
</body>
</html>
JS (Changed the way the filter is defined to make a new 'Angular' filter)
angular.module('plunker', ['ui.bootstrap']);
var TabsDemoCtrl = function ($scope) {
$scope.okFilterBool = "all";
$scope.items = [
{ name: 'A'},
{ name: 'B'},
{ name: 'C'}
];
};
angular.module("plunker").filter("filterItem", function(){
return function(array, okFilterBool){
if(okFilterBool == "all"){ return array; }
return [];
}
})

Related

Create a handsontable in ng-switch

I would like to use a handsontable inside a ng-switch: when we select handsontable, it shows a normal and editable handsontable.
JSBin
HTML:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://docs.handsontable.com/pro/1.8.2/bower_components/handsontable-pro/dist/handsontable.full.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://docs.handsontable.com/pro/1.8.2/bower_components/handsontable-pro/dist/handsontable.full.min.css">
</head>
<body ng-app="">
<select ng-model="myVar">
<option value="dogs">Dogs
<option value="handsontable">handsontable
</select>
<div ng-switch="myVar">
<div ng-switch-when="dogs">
<p>Welcome to a world of dogs.</p>
</div>
<div ng-switch-when="handsontable">
<div id="example1" class="hot handsontable htRowHeaders htColumnHeaders"></div>
</div>
</div>
</body>
</html>
JavaScript:
var example1 = document.getElementById('example1');
var settings1 = { data: [['A1', 'B1'], ['A2', 'B2']] };
var hot1 = new Handsontable(example1, settings1);
Unlike this working example, the cells in the table are NOT editable. So I am wondering if there is something missing. For example in the working example, the creation of the table is wrapped by document.addEventListener("DOMContentLoaded", function() { ... }), should I wrap the javascript code in this example by something to make sure we create the table only after we ng-switch to handsontable?
So as #Mistailis suggested, we could use ngHandsontable.
JSBin
HTML:
<!DOCTYPE html>
<html>
<head>
<base href="http://handsontable.github.io/ngHandsontable/node_modules/">
<link rel="stylesheet" href="handsontable/dist/handsontable.full.css">
<script src="angular/angular.js"></script>
<script src="handsontable/dist/handsontable.full.js"></script>
<script src="../dist/ngHandsontable.js"></script>
</head>
<body ng-app="app">
<select ng-model="myVar">
<option value="dogs">Dogs
<option value="handsontable">handsontable
</select>
<div ng-switch="myVar">
<div ng-switch-when="dogs">
<p>Welcome to a world of dogs.</p>
</div>
<div ng-switch-when="handsontable">
<div ng-controller="MainCtrl as ctrl">
<hot-table datarows="ctrl.db.items"></hot-table>
</div>
</div>
</div>
</body>
</html>
JavaScript:
function dataFactory () { };
dataFactory.$inject = [];
angular.module('ngHandsontable').service('dataFactory', dataFactory);
function MainCtrl(dataFctory) {
this.db = { items: [[5, 6], [7, 8]] };
}
MainCtrl.$inject = ['dataFactory'];
angular
.module('app', ['ngHandsontable'])
.controller('MainCtrl', MainCtrl);

Angularjs ng-fx animation applied to the wrong element

I have created a simple app with simple animations where I can add and remove items to an array (used ng-fx for animations), but I have a problem.
When I try to add new elements, I get ng-repeat duplicate error. I fixed it by adding track by $index, but this time a new error occurs. If I try to remove an element from the list, wrong one is being animated.
Here's my plnkr
http://plnkr.co/edit/hKk9VGHIE1GT2i3P8TtT?p=preview
Here's my code.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.5.0" data-semver="1.5.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script src="angular-animate.min.js"></script>
<script src="ng-fx.js"></script>
</head>
<body ng-app="app">
<div ng-controller="FirstController">
<div ng-repeat="name in names track by $index" class="fx-fade-normal">
{{name}}
<input type="submit" value="Remove" ng-click="remove($index)">
</div>
<input type="text" ng-model="name" />
<input type="submit" value="Add" ng-click="add()">
</div>
<script>
angular.module('app', ['ngAnimate', 'ng-fx']);
angular.module('app').controller('FirstController', ["$scope", function($scope) {
$scope.names = ["first", "second", "third", "fourth"];
$scope.add = function() {
$scope.names.push($scope.name);
};
$scope.remove = function($index) {
$scope.names.splice($index, 1);
};
}]);
</script>
</body>
</html>
It's simple change ng-repeat="name in names track by $index" to ng-repeat="name in names track by $id(name)"

AngularJS: "$http.get" with input URL

I'm new to AngularJS and am trying to use it to link up with a simple web API I have in place. I already have URLs that return JSON data in the format: http://127.0.0.1:8000/posts/ followed by a date in the format YYYY-MM-DD. (example would be http://127.0.0.1:8000/posts/2015-07-28)
I have an input text box which I want to use to get the JSON data from my API and list it out, meaning if I enter 2015-07-28 into the input box, it should pull the JSON data from the API appropriately without a page refresh by appending the string value from the input box onto whatever URL I want (in this case that would be http://127.0.0.1:8000/posts/).
Here is what I have as of right now:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script>
var ListingApp = angular.module('ListingApp', []);
ListingApp.controller('PostCtrl', function($scope, $http) {
$scope.select = "";
var postJSON = "http://127.0.0.1:8000/posts/" + $scope.select;
console.log(postJSON);
$http.get(postJSON)
.then(function(res) {
$scope.posts = res.data;
console.log($scope);
});
});
</script>
</head>
<body ng-app="ListingApp">
<div ng-controller="PostCtrl">
<form name="dateForm">
<input type="text" id="dp" name="datepicker" ng-model="select" placeholder="Enter Date">
</form>
<span ng-bind="select" style="color: red">{{ dateForm.datepicker }}</span>
<ul>
<li ng-repeat-start="post in posts">
pk: {{ post.pk }}
</li>
<li>
author: {{ post.author }}
</li>
<li ng-repeat-end>
category: {{ post.category }}
</li>
</ul>
</div>
<!-- Importing jQuery -->
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
</body>
</html>
Use ng-change or watch your model. Depending on your input you may want to use the debounce in ng-model-options.
var ListingApp = angular.module('ListingApp', []);
ListingApp.controller('PostCtrl', function($scope, $http) {
$scope.select = "";
var postJSON = "http://127.0.0.1:8000/posts/" + $scope.select;
console.log(postJSON);
function getPost() {
$http.get(postJSON)
.then(function(res) {
$scope.posts = res.data;
console.log($scope);
});
}
// option #1 with ng-change="change()"
$scope.change = function() {
getPost();
}
// option #2 with watch
$scope.$watch('select', function (val, old) {
console.log(val);
getPost();
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
</head>
<body ng-app="ListingApp">
<div ng-controller="PostCtrl">
<form name="dateForm">
<input type="text" id="dp" name="datepicker" ng-model-options="{ debounce: 500 }" ng-change="change()" ng-model="select" placeholder="Enter Date">
</form>
<span ng-bind="select" style="color: red">{{ dateForm.datepicker }}</span>
<ul>
<li ng-repeat-start="post in posts">
pk: {{ post.pk }}
</li>
<li>
author: {{ post.author }}
</li>
<li ng-repeat-end>
category: {{ post.category }}
</li>
</ul>
</div>
<!-- Importing jQuery -->
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
</body>
</html>

Loading image at the time of onclick event using angularjs is not working

I want to add data at the time of onclick event. Need to load image at the time of onclick event, after a small time interval add data. But my image is continuously loading. Any body give any suggestion.
My code is:
<!DOCTYPE html>
<head>
<title>Learning AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js" type="text/javascript"></script>
<script language="javascript">
function ContactController($scope) {
$scope.contacts = [];
$scope.items = [ ];
$scope.add = function() {
setTimeout(function() {
$scope.$apply(function() {
$scope.items[0].lateLoader = ' xxxx ';
});
}, 1000);
$scope.count=$scope.count+1;
$scope.contacts.push($scope.newcontact);
$scope.newcontact = "";
}
}
</script>
</head>
<body >
<div ng-app="" ng-controller="ContactController">
<p>{{items.lateLoader}}
<i ng-hide="items.lateLoader"><img src="Filling broken ring.gif"></i>
</p>
{{ contacts.length }}
Content:<input type="text" ng-model="newcontact" />
<button ng-click="add()">Add</button>
<ul style="list-style-type: none;">
<li ng-repeat="contact in contacts"> <input name="" type="checkbox" value="">{{ contact }}</li>
</ul>
</div>
</body>
</html>
In your example I found a lot of mistakes. The HTML tag is not defined at the top, wrong use of angularJs and Angular module is not created properly etc.
I fixed all the mistakes. I hope it can help you.
Plunkr link: http://plnkr.co/edit/no8WOHdEc9wc3dHzzITv?p=preview
<!DOCTYPE html>
<html ng-app="app">
<head>
<title>Learning AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script >
angular.module("app",[]).controller('ContactController',['$scope',
function($scope) {
$scope.contacts = [];
$scope.items = [];
$scope.add = function() {
setTimeout(function() {
$scope.$apply(function() {
$scope.items.lateLoader = 'xxxx ';
});
}, 1000);
//$scope.count=$scope.count+1;
$scope.contacts.push($scope.newcontact);
$scope.newcontact = "";
}
}
]);
</script>
</head>
<body >
<div ng-controller="ContactController">
<p>{{items.lateLoader}}
<i ng-hide="items.lateLoader">
<img src="https://encrypted-tbn1.gstatic.com
/images?q=tbn:ANd9GcQTaHe0F0J39SXbiRF43pz2wtyfD6kypCMrLxhWPkq9EACNgwO0iaMbJFM">
</i>
</p>
{{contacts.length}}
Content:<input type="text" ng-model="newcontact" />
<button ng-click="add()">Add</button>
<ul style="list-style-type: none;">
<li ng-repeat="contact in contacts">
<input name="" type="checkbox" value="">{{ contact }}
</li>
</ul>
</div>
</body>
</html>
And for more detail of angularJs please visit these links:(https://angularjs.org/)
(http://www.w3schools.com/angular/default.asp)

unable to get angular ng-repeat group by filter working with dynamic group term

I have been trying for days to get a working version of a grouping filter for Angular. The goal is to group and filter a list of items, using dynamic group and search terms. The end product will have two levels of ng-repeats as well as filter terms, but below I've distilled the core issue to just a single ng-repeat and no search filtering.
The issue is described in this question, namely that I get "10 digest" errors in the JS console. I have tried the suggestion in that thread, namely that I use _.memoize(). This works for the initial load, but somehow doesn't update the ng-repeat when I update the model. I'm also unable to determine how "track by" would work for me.
For example code desired output is:
A selected: "One"
B selected: "tres uno"
Here is the version with digest errors (check the JS console), but with output working as desired:
http://plnkr.co/9TJvZk
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}]
return
});
app.filter('myFilter', function() {
return function(items, filter_items) {
return _.groupBy(items, filter_items.group_1);
}
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in items| myFilter:filter_items">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>
And error free, but not updating when model does:
http://plnkr.co/N41D2Y
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}]
return
});
app.filter('myFilter', function() {
return _.memoize(function(items, filter_items) {
return _.groupBy(items, filter_items.group_1);
}
);
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in items| myFilter:filter_items">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>
How do I get working dynamic grouping in AngularJS without the digest errors?
you mean like this
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}];
return;
});
app.filter('myFilter', function() {
var m = {};
return function(items, filter_items) {
return (filter_items.group_1 in m) ? m[filter_items.group_1] : (m[filter_items.group_1] = _.groupBy(items, filter_items.group_1) );
}
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in items| myFilter:filter_items">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>
I updated the code above as well as the plunker, just to illustrate your code is workable. But this angular-filter project is awesome, check it out.
The reason for the digest error is that each call to _.groupBy returns a new object, so every time angular checks it against the old value it is different, leading to another digest.
As the list is only filtered when filter_items.group_1 changes, it's simple to watch this in the controller and perform the group by there:
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}];
$scope.$watch('filter_items.group_1', function (group) {
$scope.groupedItems = _.groupBy($scope.items, group);
});
});
Then:
<div ng-repeat="(group1, g_items) in groupedItems">
<h2>{{group1}}</h2>
</div>
I believe you can achieve the same result without using a filter. I have successfully achieved this by using a watcher in the controller and grouping in the watcher function. This doesn't have the 10 digest errors and would work when your selection changes.
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}]
$scope.$watch('filter_items.group_1', function(newValue){
$scope.grouped = _.groupBy($scope.items, newValue)
})
return
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in grouped">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>

Resources