I'm trying to make an editable list of items. There is an editing mode of each item.
HTML:
<ul ng-controller="ItemCtrl">
<li ng-repeat="item in items">
<div class="edit-off" ng-hide="editMode">...</div>
<div class="edit-on" ng-show="editMode">...</div>
<button ng-click="toggleEdit()">Edit</button>
</li>
</ul>
JavaScript:
angular.module("app", [])
.controller("ItemCtrl", function($scope) {
$scope.items = [...]; // list of items
$scope.editMode = false;
$scope.toggleEdit = function() {
$scope.editMode = !$scope.editMode;
};
});
I know that this code isn't correct since I attached editMode to the controller scope, not to ngRepeat scope. With this code, whenever I click at any button, all items will turn into editing mode.
All I want is that every item has its own editMode property in its scope, so that I can edit them individually.
put your property on each item:
<ul ng-controller="ItemCtrl">
<li ng-repeat="item in items">
<div class="edit-off" ng-hide="item.editMode">...</div>
<div class="edit-on" ng-show="item.editMode">...</div>
<button ng-click="toggleEdit(item)">Edit</button>
</li>
</ul>
angular.module("app", [])
.controller("ItemCtrl", function($scope) {
$scope.items = [...]; // list of items
$scope.toggleEdit = function(item) {
item.editMode = !item.editMode;
};
});
You can use $index like this:
angular.module("app", [])
.controller("ItemCtrl", function($scope) {
$scope.items = [...]; // list of items
$scope.editMode = [];
$scope.toggleEdit = function(index) {
$scope.editMode[index] = !$scope.editMode[index];
};
});
HTML:
<ul ng-controller="ItemCtrl">
<li ng-repeat="item in items">
<div class="edit-off" ng-hide="editMode[$index]">...</div>
<div class="edit-on" ng-show="editMode[$index]">...</div>
<button ng-click="toggleEdit($index)">Edit</button>
</li>
</ul>
Demo: https://jsfiddle.net/iRbouh/rftfx7j4/
You can add the property in each item and use it to edit.
$scope.items = [{name: 'misko', gender: 'male'},{name: 'misko1', gender: 'male'}];
angular.forEach($scope.items, function(obj) {
obj["editMode"] = false
});
in view
<ul ng-controller="ItemCtrl">
<li ng-repeat="item in items">
<div class="edit-off" ng-hide="editMode[$index]">...</div>
<div class="edit-on" ng-show="editMode[$index]">...</div>
<button ng-click="item.editMode = !item.editMode">Edit</button>
</li>
</ul>
Use $index.
HTML:
<ul ng-controller="ItemCtrl">
<li ng-repeat="item in items track by $index">
<div class="edit-off" ng-hide="editMode">...</div>
<div class="edit-on" ng-show="editMode">...</div>
<button ng-click="toggleEdit($index)">Edit</button>
</li>
</ul>
JS:
angular.module("app", [])
.controller("ItemCtrl", function($scope) {
$scope.items = [...]; // list of items
$scope.toggleEdit = function($index) {
setEditMode($scope.items[$index]);
};
});
function setEditMode(item) {
item.editMode = false;
}
Add the editMode attribute to each item, as said in #John's answer.
Here's the working Plunker:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [
{ id:2, ds: 'test1' },
{ id:2, ds: 'test2' },
{ id:2, ds: 'test3'}]; // list of items
$scope.toggleEdit = function($index) {
$scope.items[$index].editMode = !$scope.items[$index].editMode;
};
});
There are a lots way can implement this, see example:
<ul ng-controller="ItemCtrl">
<li ng-repeat="item in items">
<div class="edit-off" ng-hide="editMode[$index]">{{editMode[$index]}}</div>
<div class="edit-on" ng-show="editMode[$index]">{{editMode[$index]}}</div>
<button ng-click="toggleEdit($index)">Edit</button>
</li>
var myApp = angular.module("myApp", [])
.controller("ItemCtrl", function($scope) {
$scope.items = ["aaa","bbb","ccc"]; // list of items
$scope.editMode = [true,true,true];
$scope.toggleEdit = function(index) {
$scope.editMode[index] = !$scope.editMode[index];
};
});
http://jsfiddle.net/Lvc0u55v/7052/
Related
I trying to create a unordered list using controller and view page. Please find the controller below:
(function() {
'use strict';
angular
.module('app.sdb')
.controller('SdbController', SdbController)
SdbController.$inject = ['logger'];
/* #ngInject */
function SdbController(logger) {
var vm = this;
vm.models = {
selected: null,
lists: {"A": [], "B": []}
};
for(var i=1;i<=3;i++) {
vm.models.lists.A.push({label: "Item A" + i});
vm.models.lists.B.push({label: "Item B" + i});
}
activate();
function activate() {
vm.title = 'Safe Digital Board';
logger.info('Activation', 'Sdb Controller', 'Template Rendered');
}
}
})();
Please find the mark up below:
<div>
<ul>
<li ng-repeat="item in vm.models"> Hello {{item.label}} </li>
</ul>
</div>
But am getting only the below O/P:
Hello
Hello
Seeking help... Please advise
Problem is with your model object. Your ng-repeat should be ng-repeat="item in vm.models.lists.A"
Please find a working plunker
<div>
<ul>
<li ng-repeat="item in vm.models.lists.A"> Hello {{item.label}} </li>
</ul>
</div>
To show both lists you need to write your template as shown below:
<div>
<ul ng-repeat="items in vm.models.lists">
<li ng-repeat="item in items"> Hello {{item.label}} </li>
</ul>
</div>
try using $scope and create an array for $scope.vm.models, like:
.controller('SdbController', ['$scope', $log,
function($scope, $log) {
$scope.reset = function() {
$scope.vm = {};
$scope.vm.models = [{label:"element01"},
};
$scope.reset();
}
}]);
I have a variable in my controller and would like to assign a value later, when click on a button. i.e.
var app = angular.module('myApp', ['ngRoute']);
....
var userArray = [
{name: "John", age: 25}, {name: "Jim", age: 30}
];
app.controller('Page2Controller', function($scope) {
$scope.message = 'Look! I am from page 2.';
$scope.newArray = [];
$scope.addUsers = function(){
scope.newArray = userArray;
console.log($scope.newArray);
}
}
app.config(function($routeProvider) {
$routeProvider
.when('/page2', {
templateUrl : 'pages/page2.html',
controller : 'Page2Controller'
...
page2.html
<div>
<p>{{ message }}</p>
<ul>
<li ng-repeat="user in Page2Controller.newArray">{{user.name}}</li>
</ul>
</div>
index.html
<body ng-controller="MainController">
<div id="sideMenu">
<h2>Campaign</h2>
<ul>
<li>Home</li>
<li>Page 2</li>
<li>Page 3</li>
<li>Page 4</li>
</ul>
</div>
<div ng-view></div>
</body>
I don't understand why the $scope.user is displayed in console but in html page the "ng-repeat" doesn't display the users. May it be that ng-repeat cannot display data that was added dynamically?
Can someone help me? Appreciate that.
You never called that function I guess..
var app = angular.module('myApp', []);
var userArray = [{name: "John", age: 25}, {name: "Jim", age: 30}];
app.controller('Page2Controller', function($scope) {
$scope.message = 'Look! I am from page 2.';
// $scope.newArray = [];
$scope.addUsers = function(){
$scope.newArray = userArray;
console.log($scope.newArray);
}
$scope.addUsers();
});
and html
<div ng-controller="Page2Controller">
<p>{{ message }}</p>
<ul>
<li ng-repeat="user in newArray">{{user.name}}</li>
</ul>
</div>
I have statically used your controller as i didn't implement the ngRoute.
Try switching to:
<li ng-repeat="user in scope.newArray">{{user.name}}</li>
I don't think 'Page2Controller' is known in the template context.
First of all you have need a ng-click derective where you have to click such as
<button type="button" ng-click="asigningValue()"></button>
Then in your Controller you have to assign what you want such as in controller
After that you have need to bind you assign value in the directive such as
app.controller('Page2Controller', function($scope) {
$scope.asigningValue=function(){
$scope.message = 'Look! I am from page 2.';
}
}
Then show using directive using data binding as
<p ng-bind-html="message"></p>
Hope it will be helpful!
Thank you!
how to create Custom filter angularjs javascript controller side?
i would like to search in array called segments by SegmentId, to create filter that do foreach on segments array search by SegmentId -
//Controller
$scope.GetSegmentDetails = function (id) {
$scope.SegmentName = $filter('SegmentById')($scope.segments,id);
}
//Filter
app.filter('SegmentById', function () {
return function (input, searchPerson) {
if (!searchPerson)
return input;
var results = [];
angular.forEach(input, function (person) {
}
});
return results;
}
});
You dont have to write your one filter to filter by SegmentId. Here you have an example
function MyCtrl($scope, $filter) {
$scope.data = [{"SegmentId":"1","Description":"hod Registrations"}, {"SegmentId":"2","Description":"hod Inactive"}, {"SegmentId":"3","Description":"hod testUpd"}, {"SegmentId":"8","Description":"hod test"}, {"SegmentId":"1111","Description":"hod Release"}, {"SegmentId":"12","Description":"hod Requests"}, {"SegmentId":"13","Description":"hod Welcome Back"}]
$scope.filterData = function(segmentId) {
return $filter('filter')($scope.data, { SegmentId: segmentId });
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="MyCtrl">
Full:
<ul>
<li ng-repeat="Segment in data">
{{Segment.SegmentId}}
</li>
</ul>
Filtered in View:
<ul>
<li ng-repeat="Segment in data | filter:{SegmentId:1111}">
{{Segment.SegmentId}}
</li>
</ul>
Filtered in Controller:
<ul>
<li ng-repeat="Segment in filterData(1111)">
{{Segment.SegmentId}}
</li>
</ul>
</div>
Only need to add in your controller the filter dependency and then call it.
app.controller("YourController", ['$scope', '$filter', function ($scope, $filter){
$filter('filterName')($args));
}]);
I have this tab functionality made in AngularJS and I want it to be re-usable throughout my website without having to repeat the logic. Is there a way I can make it a directive? or maybe a service?
Here is the html:
<ul class="expandingTab">
<li ng-class="{active: isSet(1)}"><span>MY GMM</span></li>
<li ng-class="{active: isSet(2)}"><span>ALL TRANSACTIONS</span></li>
</ul>
<div ng-show="isSet(1)">
<h1>Tab 1</h1>
</div>
<div ng-show="isSet(2)">
<h1>Tab 2</h1>
</div>
Here is the JS:
var myApp = angular.module('myApp', []);
myApp.controller('TabController', ['$scope', function($scope) {
$scope.tab = 1;
$scope.setTab = function(tab) {
$scope.tab = tab;
};
$scope.isSet = function(checkTab) {
return $scope.tab === checkTab;
};
}]);
EDIT
I really would like to just have the functionality in a service and be able to inject it as a dependency to controllers that will use it. This way I can keep all the content in the view where I want it. I feel like my logic is close, but I still can't get it working. Can anyone tell me what I am doing wrong?
HTML
<ul class="expandingTab">
<li ng-class="{active: tabs.toggleTabs.isSet(1)}"> <span>Tab 1</span></li>
<li ng-class="{active: tabs.toggleTabs.isSet(2)}"><span>Tab 2</span></li>
</ul>
<div ng-show="tabs.toggleTabs.isSet(1)">
<h1>Tab 1</h1>
</div>
<div ng-show="tabs.toggleTabs.isSet(2)">
<h1>Tab 2</h1>
</div>
Controller
var app = angular.module('myApp', ['services']);
app.controller('TabController', ['$scope', 'toggleTabs',function($scope, toggleTabs) {
}]);
Service
var tabsApp = angular.module('services', []);
tabsApp.service('toggleTabs', function() {
this.tab = 1;
this.setTab = function(tabSelected) {
this.tab = tabSelected;
}
this.isSet = function(checkTab) {
return this.tab === checkTab;
}
});
And here is a Plunker with all this code: http://plnkr.co/edit/liT7BIGlIRg9boH81NaY?p=preview
In response to your comments, here is an example that shows how you can inject content into the directive to make it more reusable. It doesn't use tabs, but it illustrates the concept. JsBin example.
HTML
<body ng-controller="testController">
<header bf-nav navs="navs"></header>
</body>
JavaScript
(function() {
'use strict';
var app = angular.module('test', []);
app.directive('bfNav', navDirective);
function navDirective() {
return {
restrict: 'AE',
scope: {
navs: '='
},
template: '<nav class="navbar navbar-default" role="navigation"><div class="container-fluid"><ul class="nav navbar-nav"><li ng-repeat="nav in navs" ng-click="setNav(nav.index)" ng-class="{ active: isActive(nav.index) }">{{nav.title}}</li></ul></div></nav>',
controller: navController
};
}
function navController($scope) {
$scope.activeNav = 1;
$scope.isActive = function (index) {
return $scope.activeNav === index;
};
$scope.setNav = function (index) {
$scope.activeNav = index;
};
}
app.controller('testController', ['$scope', testController]);
function testController($scope) {
$scope.navs = [
{ index: 1, title: 'Nav 1' },
{ index: 2, title: 'Nav 2' }
];
}
})();
Your directive is not working because you have not specified a 'template' for it (your html) in conjunction with using an isolate scope (scope: {}). Basically the directive cannot talk to the html that you have put the tabs on. (among other things)
Try:
ocApp.directive('tabs', function(){
return{
restrict: 'A',
scope: {},
templateUrl: 'tabs.html', //Put your html into a seperate file and add the path here
controller: function($scope){
$scope.tab = 1;
$scope.setTab = function(tab){
$scope.tab = tab;
};
$scope.isSet = function(checkTab){
return $scope.tab === checkTab;
};
}
};
});
For tabs.html
<ul class="expandingTab">
<li ng-class="{active: isSet(1)}"><span>MY GMM</span></li>
<li ng-class="{active: isSet(2)}"><span>ALL TRANSACTIONS</span></li>
</ul>
<div ng-show="isSet(1)">
<h1>Tab 1</h1>
</div>
<div ng-show="isSet(2)">
<h1>Tab 2</h1>
</div>
And for index.html you would use
<div tabs></div>
or
<tabs></tabs>
I'd recommend this reference for directives (there are many other resources on the googles and on SO)
I ended up doing this as a service and it seems to be just what I wanted. I can keep the html in the view and just inject the service into whatever controller I want to use tabs on here is the code:
HTML
<ul class="expandingTab">
<li ng-class="{active: .toggleTabs.isSet(1)}"><span>Tab 1</span></li>
<li ng-class="{active: toggleTabs.isSet(2)}"><span>Tab 2</span></li>
</ul>
<div ng-show="toggleTabs.isSet(1)">
<h1>Tab 1</h1>
</div>
<div ng-show="toggleTabs.isSet(2)">
<h1>Tab 2</h1>
</div>
Controller
var app = angular.module('myApp', ['services']);
app.controller('TabController', ['$scope', 'toggleTabs',function($scope, toggleTabs) {
$scope.toggleTabs = toggleTabs;
}]);
Service
var tabsApp = angular.module('services', []);
tabsApp.service('toggleTabs', function() {
this.tab = 1;
this.setTab = function(tabSelected) {
this.tab = tabSelected;
}
this.isSet = function(checkTab) {
return this.tab === checkTab;
}
});
I've been trying to figure this out for like 10 hours now. Time to ask for help!
I'm trying to pass a variable from an angular.js template variable to bootbox for a nice looking confirmation prompt.
Assume that I have the following (abbreviated for clarity):
<script>
$(document).on("click", ".confirm", (function(e) {
e.preventDefault();
bootbox.confirm("This needs to be the value of {{item.name}}", function(confirmed) {
console.log("Confirmed: "+confirmed);
});
}));
</script>
which is executed as such:
<ul class="list-group">
<li ng-repeat="item in items">
<span class="glyphicon glyphicon-fire red"></span>
</li>
</ul>
When the user clicks the link, I would like a the confirmation box to appear, and I need to include attributes like {{item.name}} and {{item.row}} that are specific to this element in the list.
I have read up on the $compile functionality of angular.js and I got it working in so far as having a <div compile="name"> but that doesn't help me for retrieving a single entry out of my list as I am iterating. Any help would be appreciated!
Applied as a directive...
HTML:
<body ng-app="myApp" ng-controller="MainController">
<ul class="list-group">
<li ng-repeat="item in items">
<confirm-button name="{{item.name}}"></confirm-button>
</li>
</ul>
</body>
JS:
angular.module('myApp', [])
.controller('MainController', function($scope) {
$scope.items = [
{ name: 'one' },
{ name: 'two' },
{ name: 'three' }
];
})
.directive('confirmButton', function(){
return {
restrict: 'E',
scope: { name: '#' },
template: '<span class="glyphicon glyphicon-fire red" ng-click="confirm(name)">Button</span>',
controller: function($scope) {
$scope.confirm = function(name) {
bootbox.confirm("The name from $scope.items for this item is: " + name, function(result){
if (result) {
console.log('Confirmed!');
} else {
console.log('Cancelled');
}
});
};
}
}
});
Working plunk
This is a simple approach, but depending on what you're trying to do it may not suit you:
var app = angular.module('app', []);
app.controller('AppCtrl', function ($scope) {
$scope.items = [
{ name: "Bla bla bla bla?", url: "http://stackoverflow.com" },
{ name: "Ble ble ble ble?", url: "http://github.com" }
];
$scope.confirm = function (item) {
bootbox.confirm("Confirm?", function (confirmed) {
alert('Confirmed: '+ confirmed +'. Url: '+ item.url);
});
};
});
In your html:
<div ng-app='app' ng-controller="AppCtrl">
<ul class="list-group">
<li ng-repeat="item in items">
<a ng-click="confirm(item)">
<span class="glyphicon glyphicon-fire red"></span>
{{ item.name }}
</a>
</li>
</ul>
</div>
Depending on what you want, maybe you should check out the directives: https://docs.angularjs.org/guide/directive