ng-repeat passes only first element to the function - angularjs

I have following code in my app:
<li ng-repeat="data in array">
<ul class="social-share">
<li>
<i class="fa fa-share-alt"></i>Share
<div id="myPopover" class="hide">
<strong>Social Share</strong>
<ul class="social-spacing">
<li><a class="btn btn-primary share-button" title="" data-original-title="" href="" ng-click="share(data.translation)">Facebook</a></li>
</ul>
</div>
</li>
</ul>
<p class="eng-translation">{{data.translation}}</p>
</li>
I'm using an angular directive to show the popover which contains social sharing options. Directive is as follows:
myApp.directive('popover', function() {
return function(scope, elem) {
elem.popover({
container: 'body',
html: true,
content: function () {
var clone = $($(this).data('popover-content')).clone(true).removeClass('hide');
return clone;
}
}).click(function(e) {
e.preventDefault();
});
}
});
All of the data in array displays properly as is supposed to be with ng-repeat. But, when I click on the Facebook share button, it only sends the first element of the array to the function "share".
If I don't use popover, it works fine.
Any help on this would be really kind.
Edit: Array object added
$scope.array = [
{
'translation': 'translation-1'
},
{
'translation': 'translation-2'
},
{
'translation': 'translation-3'
},
{
'translation': 'translation-4'
},
{
'translation': 'translation-5'
},
{
'translation': 'translation-6'
},
{
'translation': 'translation-7'
}
];

You can find the working version of your code below here. Are you missing to add ng-app="app" or ng-controller="myController" elements?
var myApp = angular.module('app', []);
myApp.controller('myController', ['$scope', function($scope) {
$scope.myArray = [
{
'translation': 'translation-1'
},
{
'translation': 'translation-2'
},
{
'translation': 'translation-3'
},
{
'translation': 'translation-4'
},
{
'translation': 'translation-5'
},
{
'translation': 'translation-6'
},
{
'translation': 'translation-7'
}
];
$scope.share = function($index) {
alert($scope.myArray[$index].translation);
};
}]);
myApp.directive('popover', function() {
return function(scope, elem) {
elem.popover({
container: 'body',
html: true,
content: function () {
var clone = elem.siblings('#myPopover').clone(true).removeClass('hide').css("display", "inherit");
return clone;
}
}).click(function(e) {
e.preventDefault();
});
}
});
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<div ng-app="app">
<div ng-controller="myController">
<li ng-repeat="myData in myArray">
<ul class="social-share">
<li>
</i>Share
<div id="myPopover" class="hide">
<strong>Social Share</strong>
<ul class="social-spacing">
<li><a class="btn btn-primary share-button" title="" data-original-title="" href="" ng-click="share($index)">Facebook</a></li>
</ul>
</div>
</li>
</ul>
<p class="eng-translation">{{myData.translation}}</p>
</li>
</div>
</
</body>
</html>

Related

Insert checked checkbox value at the end

I have a check box with a button.
When I click button checked, checkbox value should be pushed into an array. But it adds at the beginning of an array. I want to add checked checkbox value at the end of the array when clicking the button.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.4/angular.min.js"></script>
<script src="https://rawgithub.com/angular-ui/ui-sortable/master/src/sortable.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app='test' ng-controller="Test">
<ul>
<li ng-repeat="album in albums">
<input type="checkbox" ng-model="album.selected" value={{album.name}} /> {{album.name}}
</li>
</ul>
<button type='button' ng-click="save()">Save</button><br>
<div ui-sortable="sortableOptionsList[0]" >
{{albumNameArray}}
</div>
<div ui-sortable="sortableOptionsList[0]">
<div class="app" ng-repeat="app in albumNameArray"> {{app.name}}</div>
</div>
</body>
</html>
<script>
angular.module('test', ['ui.sortable'])
.controller('Test', function($scope){
$scope.albums = [{
id: 1,
name: 'test1',
checked : false
},
{
id: 2,
name: 'test2',
checked : false
},
{
id: 3,
name: 'test3',
checked : false
}];
function createOptions (listName) {
console.log('outout');
var _listName = listName;
var options = {
placeholder: "app",
connectWith: ".apps-container",
helper: function(e, item) {
console.log("list " + _listName + ": helper");
return item;
}
};
return options;
}
$scope.sortableOptionsList = [createOptions('A'), createOptions('B')];
$scope.save = function(){
$scope.albumNameArray = [];
angular.forEach($scope.albums, function(album){
console.log(album.selected);
if(album.selected)
{
$scope.albumNameArray.push(album.name);
}
});
}
})
</script>
I have the perfect solution for your query. You just need to make a small change on the logic. Since you want to track the sequence on which the checkboxes are selected, i would suggest you the proper way in AngularJS, using ng-change on the checkbox.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.4/angular.min.js"></script>
<script src="https://rawgithub.com/angular-ui/ui-sortable/master/src/sortable.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app='test' ng-controller="Test">
<ul>
<li ng-repeat="album in albums">
<input type="checkbox" ng-model="album.selected" value={{album.name}} ng-change='trackOrder(album)' /> {{album.name}}
</li>
</ul>
<button type='button' ng-click="save()">Save</button><br>
<div ui-sortable="sortableOptionsList[0]" >
{{albumNameArray}}
</div>
<div ui-sortable="sortableOptionsList[0]">
<div class="app" ng-repeat="app in albumNameArray"> {{app.name}}</div>
</div>
</body>
</html>
<script>
angular.module('test', ['ui.sortable'])
.controller('Test', function($scope){
$scope.albumArray = [];
$scope.albums = [{
id: 1,
name: 'test1',
checked : false
},
{
id: 2,
name: 'test2',
checked : false
},
{
id: 3,
name: 'test3',
checked : false
}];
function createOptions (listName) {
console.log('outout');
var _listName = listName;
var options = {
placeholder: "app",
connectWith: ".apps-container",
helper: function(e, item) {
console.log("list " + _listName + ": helper");
return item;
}
};
return options;
}
$scope.sortableOptionsList = [createOptions('A'), createOptions('B')];
$scope.trackOrder = function(album){
//add album in the array
if(album.selected){
$scope.albumArray.push(album.name);
}else{
//remove album fron the array
var index = $scope.albumArray.indexOf(album.name);
$scope.albumArray.splice(index,1);
}
}
$scope.save = function(){
//if you want the value on albumNameArray on click on save use this else you can
//use the $scope.albumArray directly
$scope.albumNameArray = angular.copy($scope.albumArray);
}
})
</script>
Here is the plunkr link PLUNKR
use unshift.
$scope.albumNameArray.unshift(album.name);

Unable to get data from JSON file in AngularJS

I'm new in angularjs, I'm trying to load data from my JSON file on view. JSON file have some list of lists using li. But does not get showed on my view.
Here is my 'index.html' file
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ng-repeat="item in navbaritem.navigation">
<a class="{{ item.class }}" href="#" ng-href="{{ item.url }}">{{ item.title }}</a>
</li>
</ul>
</div>
Here is my controller.js
(function(){
var app = angular.module('myapp', []);
app.controller('mycntrl', function($scope, $http) {
$scope.navbaritem = [];
$http.get('pages/navbar.json').success(function(data) {
$scope.navbaritem = data;
}, function (err,data) {
if(err){
return console.log(err);
}
console.log(data);
});
});
});
Here is my 'pages/navbar.json' file
{
"general":{
"logo":"images/logo.jpeg",
"name" : "Company Name"
},
"navigation":[
{
"title":"Home",
"link":"#"
},
{
"title":"About",
"link":"#"
},
{
"title":"Services",
"link":"#"
},
{
"title":"Contact",
"link":"#"
}
]
}
and my output is like this {{item.title}} and also I'm getting the error
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.6.1/$injector/modulerr?p0=myapp&p1=Error%3A%2…localhost%2Fangular-theme%2Fassets%2Fangularjs%2Fangular.min.js%3A21%3A332)
Here is a working example :
Note: As SO snippet editor does not allow additional files, I simulated a $http call in my service with $timeout which also return a promise.
Snippet
(function() {
'use strict';
angular.module('app', []);
angular.
module('app')
.controller('ExampleController', ['$scope', 'MyService', function($scope, MyService) {
// Call service to get navbar items
MyService.getNavbarItems()
.then(function(data) {
// Once promise success, update $scope
$scope.navbaritem = data;
});
}])
.factory('MyService', ['$timeout', function($timeout) {
return {
getNavbarItems: function() {
// Simulate 250ms $http api call
// Use return $http.get('/api/navbar/items') in your code
return $timeout(function() {
return {
"general": {
"logo": "images/logo.jpeg",
"name": "Company Name"
},
"navigation": [{
"title": "Home",
"link": "/home",
"class": "item"
},
{
"title": "About",
"link": "/about"
},
{
"title": "Services",
"link": "/services"
},
{
"title": "Contact",
"link": "/contact"
}
]
}
}, 250);
}
}
}])
})();
<!doctype html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>
</head>
<body ng-controller="ExampleController">
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li ng-repeat="item in navbaritem.navigation">
<a class="{{ item.class }}" href="#" ng-href="{{ item.link }}">{{ item.title }}</a>
</li>
</ul>
</div>
</body>
</html>

Button click count for each list item in AngularJS

I have a list and I want to get the button click count for each item separately.
I have created an example example but that has increasing all items. Please help. One Important thing, the JSON doesn't have 'count' key.
var myApp = angular.module('myApp',[]);
var jsonInfo = {"count":["one", "two", "three", "four"]}
function MyCtrl($scope) {
$scope.data =jsonInfo;
$scope.counter = 0;
$scope.count = function (inc) {
$scope.counter += inc;
};
}
One way you can do this by Modifying the array in to object array
var jsonInfo = {"count":[{"name":"one",count:0} ,{"name":"two",count:0} ,{"name":"three",count:0} ,{"name":"four",count:0}]}
Now modify the html like this
<li ng-repeat="list in data.count">
<a href="#" ng-click="count(list)">
<span>{{list.name}}</span>
<span style="display: block;">Count: {{list.count}}</span>
</a>
</li>
Then pass the obj as parameter to function and increase the count of that object
function MyCtrl($scope) {
$scope.data =jsonInfo;
$scope.counter = 0;
$scope.count = function (inc) {
inc.count = inc.count + 1
};
}
Demo
Try this
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript">
var myApp = angular.module('myApp', [])
.controller('MyCtrl', function MyCtrl($scope) {
var jsonInfo = [
{
count: 1,
name: "one"
},
{
count: 1,
name: "two"
},
{
count: 1,
name: "three"
},
{
count: 1,
name: "four"
}]
$scope.data = jsonInfo;
$scope.counter = 0;
$scope.count = function (inc) {
inc.count = inc.count + 1;
};
})
</script>
</head>
<body>
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="list in data">
<a href="#" ng-click="count(list)">
<span>{{list.name}}</span>
<span style="display: block;">Count: {{list.count}}</span>
</a>
</li>
</ul>
</div>
</body>
</html>

Angularjs not working when using IE 9

I have an angularjs app, where I am using ng-app on div, and not the html.
The application works fine in IE>=10 and chrome,FF.
In IE 9, none of the ng- code is executed, breakpoint doesn't enter my custom angular scripts, and html shows {{}}.
It seems like angularjs is not getting bootstrapped.
I tried manually bootstrapping using
$(document).ready(function () {
angular.element(document).ready(function () {
angular.bootstrap(document.getElementById("HomeGrid"), ['ngGridApp']);
Doing this doesn't show the {{}} anymore, but no data is coming.
I am getting data using $http get like this
var User = $("#UserID").text();
$http({
method: 'POST',
url: '/Home/GetData/',
data: { UserName: $("#UserID").text() }
}).success(function (data) {
$scope.GridData = angular.fromJson(data);
});
Angularjs 1.3.2
_Layout.cshtml
<!DOCTYPE html>
<html lang="en" xmlns:ng="http://angularjs.org" >
<head>
<meta charset="utf-8" />
<title></title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
<!--[if lte IE 9]>
<script src="xdomain.js" slave="http://example.org/proxy.html"></script>
<![endif]-->
#Scripts.Render("~/bundles/Angular")
#Scripts.Render("~/bundles/modernizr")
#Styles.Render("~/Angular/css")
<script src="~/Scripts/jquery-ui-1.10.4.custom.min.js"></script>
<script type="text/javascript">
$.ajaxSetup(
{
cache: false
});
$(document).ready(function () {
$(".openPopup").live("click", function (e) {
e.preventDefault();
$("#PopUp").addClass("dialog")
.attr("id", $(this)
.attr("data-dialog-id"))
.appendTo("body")
.dialog({
title: $(this)
.attr("data-dialog-title"), close: function () {
//$(this).remove();
}, modal: true, height: 400, width: 900
}).load(this.href);
});
$(".close").live("click", function (e) {
$(this).closest(".dialog")
.dialog("close");
window.location.reload();
});
});
</script>
</head>
<body>
<nav class="navbar navbar-default navbar-static-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="~/Home/Index" class="navbar-logo">
<img src="#Url.Content("~/Images/xs.png")">
<span>BillPrep</span>
</a>
</div>
<!-- Collection of nav links and other content for toggling -->
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav"></ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a id="dLabel" role="button" data-toggle="dropdown" aria-expanded="false" class="dropdown-toggle" data-target="#" href="#">
<strong>#Html.Action("LoginDisplay", "Home", new { Name = User.Identity.Name })</strong> <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li>User Settings</li>
<li>System Settings</li>
<li>#Html.ActionLink("Sign Out", "Logout", "Home")</li>
</ul>
</ul>
</div>
</div>
</nav>
<div>
#RenderSection("featured", required: false)
#RenderBody()
</div>
Homepage.cshtml
<script src="~/Scripts/angularjs/stacktrace.js"></script>
<script type="text/javascript">
$(document).ready(function () {
angular.element(document).ready(function () {
angular.bootstrap(document.getElementById("HomeGrid"), ['ngGridApp']);
// angular.bootstrap(document.getElementById("tabgrid"));
});
});
</script>
<div>
<body ng-controller="ngGridController" id="HomeGrid">
<style>
#myTabs div li.active a {
background-color: lightsteelblue;
}
.gridStyle {
border: 1px solid rgb(212,212,212);
width: 400px;
}
.bold {
color: black;
font-weight: bold;
}
</style>
<div ng-controller="TabsDemoCtrl" data-ng-init="init()" id="tabgrid">
<div id="UserID" ng-show="false">{{User}}</div>
<loading></loading>
<br />
<tabset ng-show="{{show1}}">
<tab id="Inbox" active="isFirstActive">
<tab-heading>
<span class="glyphicon glyphicon-inbox" aria-hidden="true"></span>
Inbox
</tab-heading>
<div class="ngGridStyle" ng-grid="ngGridViewInbox"></div>
</tab>
<tab id="pending" active="isSecondActive">
<tab-heading>
<span class="glyphicon glyphicon-folder-open" aria-hidden="true"></span>
show2
</tab-heading>
<div class="ngGridStyle" ng-grid="ngGridView2" ng-show={{show2}}></div>
</tab>
js file
var app = angular.module('ngGridApp', ['ngGrid', 'ui.bootstrap', 'logToServer'])
.directive('loading', function () {
return {
restrict: 'E',
replace: true,
template: '<div class="loading"><img src="http://www.mytreedb.com/uploads/mytreedb/loader/ajax_loader_blue_512.gif" width="20" height="20" />LOADING...</div>',
link: function (scope, element, attr) {
scope.$watch('loading', function (val) {
if (val)
$(element).show();
else
$(element).hide();
});
}
}
})
TabsDemoCtrl.$inject = ["$scope", "$window"];
angular.module('ngGridApp').controller('TabsDemoCtrl', TabsDemoCtrl);
function TabsDemoCtrl($scope, $window) { $scope.User = ""; }
ngGridController.$inject = ["$scope", "$http", "$interval"];
app.controller('ngGridController', ngGridController);
function ngGridController($scope, $http, $interval) {
$scope.callAtInterval = function () {
var User = $("#UserID").text();
$http({
method: 'POST',
url: '/Home/GetData/',
data: { UserName: $("#UserID").text() }
}).success(function (data) {
$scope.GridData = angular.fromJson(data);
});
Adding the solution, if it can help someone.
The issue was creation of multiple body tags, one in the master page (_Layout) and other in the main page. The ng-app was applied to the main page body tag.
Since the html was not formed properly, angularjs was not bootstrapping correctly.
Changing the body tag on main page to div, and applying ng-app to div made it work fine in IE 9

AngularJS orderby / controller behavior: controller executed on orderby

I took a sample AngularJS app and began to change it to suit my needs. Now clicking to change the orderby causes the entire controller to be reloaded. Well that's where I'm initializing the default orderby. So what I get when I click a new orderby is a flash of the proper orderby then a quick return to the default. An alert showed me the controller is getting executed but I don't know why or how to fix it.
Plunker here
index.html
<!DOCTYPE html>
<html data-ng-app="promptsApp">
<head>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
<link href="style.css" rel="stylesheet" />
</head>
<body>
<div ng-view></div>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="app.js"></script>
<script src="controllers.js"></script>
<script src="promptsService.js"></script>
</body>
</html>
app.js
var app = angular.module('promptsApp', []);
app.config(function ($routeProvider) {
$routeProvider
.when('/prompts',
{
controller: 'PromptsController',
templateUrl: 'partial.html'
})
.otherwise({ redirectTo: '/prompts' });
});
controllers.js
app.controller('PromptsController', function ($scope, promptsService)
{
init();
function init()
{
$scope.prompts = promptsService.getPrompts();
$scope.orderby='TRANSFEREE';
$scope.reverse = false;
//alert('Hi');
}
$scope.setOrder = function (orderby) {
if (orderby === $scope.orderby)
{
$scope.reverse = !$scope.reverse;
}
$scope.orderby = orderby;
};
});
promptsService.js
app.service('promptsService', function ()
{
this.getPrompts = function (user)
{
var prompts = [
{
id: 1, NOTE: 'Call client about something', CALLBACK_DATE: '12-01-2013', TRANSFEREE: 'Tom Tuttle', REG_NUM: '123456'
},
{
id: 2, NOTE: 'Notify client of delay', CALLBACK_DATE: '12-10-2013', TRANSFEREE: 'Eddie Munster', REG_NUM: '101314'
},
{
id: 3, NOTE: 'Complete paperwork', CALLBACK_DATE: '12-12-2013', TRANSFEREE: 'Mary Tyler Moore', REG_NUM: '998877'
}
];
return prompts;
};
});
partial.html
<div class="prompts">
<div class="container">
<header>
<h3>Prompts</h3>
<ul class="nav nav-pills">
<li ng-class="{'active': orderby=='CALLBACK_DATE'}">Date</li>
<li ng-class="{'active': orderby=='TRANSFEREE'}">Transferee</li>
<li> (Currently: {{orderby}})</li>
</ul>
</header>
<div>
<div class="row cardContainer">
<div class="span3 card" data-ng-repeat="prompt in prompts | orderBy:orderby:reverse">
<div class="cardHeader">{{prompt.TRANSFEREE}}</div>
<div class="cardBody">{{prompt.NOTE}}
<br># {{prompt.REG_NUM}} {{prompt.CALLBACK_DATE}}
</div>
</div>
</div>
</div>
<br />
{{prompts.length}} prompts
</div>
</div>
See Plunker here
<li ng-class="{'active': orderby=='CALLBACK_DATE'}">
<a href="" ng-click="setOrder('CALLBACK_DATE')">\
CallBack Date
</a>
</li>
<li ng-class="{'active': orderby=='TRANSFEREE'}">
<a href="" ng-click="setOrder('TRANSFEREE')">
Transferee
</a>
</li>
<li>> Currently: {{orderby}}</li>
Remove the href="#" and replace it with href="" to get the desired result.
Having href="#" causes the route to change (and become the same as before) but triggers the initialization of the controller once more.

Resources