Angularjs Manipulate each ng-repeat elements - javascript

I have a Custom directives that acts as a widget containing a list of buttons based on parameters passed in setting.
Setting passed in ng-repeat
$scope.btnGroup = [{"name":"toggle 1"},{"name":"toggle 2"}];
HTML
<div ng-controller="toggleButtonController" ng-init="init()" id="parent">
<div ng-repeat="btn in setting" style="display:inline">
<button class="btn btn-default" ng-bind="btn.name" ng-click="click()"></button>
</div>
So right now, my scenario is when i click one of the buttons, it will set the clicked button to btn-primary class and others to btn-default class and vice versa.
CONTROLLER
var app = angular.module('toggleButtonMod', [])
app.directive('toggleButton', function() {
return {
restrict: 'E',
scope: {
setting: '='
},
templateUrl: "app/Shared/togglebutton/toggleButtonView.html"
}
})
app.controller("toggleButtonController", function($scope) {
$scope.init = function() {
$scope.setupContent();
}
$scope.setupContent = function() {
}
$scope.click = function(event) {
console.log(event);
//here to change all the buttons in ng-repeat to btn-default class and the
//clicked button btn-primary class
}
})
Im stucked at the click function here..I have no idea how to manipulate each buttons in ng-repeat and modify their css class accordingly.

You can give the directive a controller and pass the directive's scope to the controller. With access to the scope, you can store a value that can be used in the template to conditionally add the class (using ngClass).
Directive:
.directive('toggleButton', function() {
return {
restrict: 'E',
scope: {
setting: '='
},
templateUrl: "app/Shared/togglebutton/toggleButtonView.html",
controller: function($scope){
$scope.toggleButton = {selected: null};
}
}
})
Template:
<div ng-repeat="btn in setting" style="display:inline">
<button class="btn" ng-class="{'btn-primary': btn === toggleButton.selected, 'btn-default': btn !== toggleButton.selected}" ng-bind="btn.name" ng-click="toggleButtonSelection(btn)"></button>
</div>
Note: Because ngRepeat creates a new scope for each item in the collection, in this case the value must be stored as an object property so that it is not shadowed in the item's scope and always references the directive's scope.
https://plnkr.co/edit/3xTpOFgpfYA99iKOi0rB?p=preview

in your html code add id attribute to button like as I have done in below code
<div ng-controller="toggleButtonController" ng-init="init()" id="parent">
<div ng-repeat="item in setting" style="display:inline">
<button class="btn btn-default" id= "item.name" ng-bind="item.name" ng-click="click($event)"></button>
</div>
$scope.click = function(event) {
var id = event.target.id;
var btn = document.getElementById(id);
if(btn.classList.contains('btn-default')){
btn.classList.remove('btn-default');
}
btn.classList.add('btn-primary');
angular.forEach(setting, function(value, key) {
var button = document.getElementById('value.name');
if(button.classList.contains('btn-primary')){
button.classList.remove('btn-primary');
}
button.classList.add('btn-default');
});
}

Related

How to hide a div in the parent controller and display a child controller inside the parent controller? -angularjs

I have a controller that displays a title nd a div. When clicking on the div, add() function is called. Now since the add() function is called, I want to hide the present div and then usingng-show or ng-if, I want to show another directive with its controller.
I want to hide addCard[index] and then show listWrapperControl. The listWrapperControl[$index] is in directive list-wrapper-controls as shown in the template.
Controller1 and its Directive
.controller('listWrapperController', ['$scope','$compile','$http', function($scope, $compile, $http){
'ngInject';
$scope.tasks=[];
function add(index){ // click on this function to hide addCard[] and display the Controller2
//$scope.listcontrols[index] = true;
$scope.listWrapperControl[index] = true;
$scope.addCard[index] = true;
//cardvalue = vm.newtitle[index];
};
}])
.directive('listWrapper', function() {
return {
restrict: 'E', // Element directive
scope:{
tasks: '=',
addCard: '=',
listWrapperControl: '='
},
controller: 'listWrapperController as listctrl',
template:
`<div class ="listwrapper" id="listwrapper" ng-repeat="task in tasks track by $index"><div id="titlebox" >
<b class ="card1" id ="cardtitle">
{{task.title}}
</b></div>
<list-wrapper-controls list-wrapper-control ="listctrl.listWrapperControl" ng-show="ctrl.listWrapperControl[$index]" id= "hidecontrols">
</list-wrapper-controls>
<div id="transparent" ng-click ="listctrl.add($index)" style ="padding-left:0%; margin-left:0;">
<a add-card = "addCard" ng-hide="addCard[$index]" style ="color:inherit">
Add a card...
</a>
</div></div>`
};
});
Controller2 and its Directive:
Display this controller
angular.module('myApp')
.controller('listWrapperControl', ['$scope','$compile','$http', function($scope, $compile, $http){
'ngInject';
}])
.directive('listWrapperControls', function() {
return {
restrict: 'E', // Element directive
controller: 'listWrapperControl as listcontrolctrl',
template: `<div ng-if="listcontrols[$index]==true" ng-show="listcontrolctrl.listWrapperControl[$index]"><textarea ng-model="listcontrolctrl.newtitle[$index]" class = "t" id="txtarea"></textarea>
<button id = "firstbutton" class ="btn btn-success nbutton" ng-click = "listcontrolctrl.addtext($index)">Add
</button><img id ="remove1" src ="remove.png" ng-click ="listcontrolctrl.removecontrols($index)"></img></div>`
};
});

Access to method in the same .factory in Angular.js

I run the factory, and excecute the function "fn_generarPopupConfirm()" in any controller.
in this method, I have now created a template. This template has a buton that has an ng-click, which calls an existing function inside the same factory. In my example I have this:
<button type="submit" class="btn btn-primary" ng-click="fn_confirmar()">
How can I do it to call it ("oElim.fn_confirmar()")?, without needing to define a function in which I define a $scope object, to call the function needed. this function is present in the same factory.
controller: function($scope){
$scope.fn_confirmar=function(){
oElim.fn_confirmar();
}
},
I need the function to be called directly "oElim.fn_confirmar()" with the ng-click event. it's possible?
this is my factory.
.factory('eliminar', function($state,$rootScope,$uibModal,popup_generico) {
var oElim= {};
oElim.fn_generarPopupConfirm = function(objeto,array,titulo,contenido) {
$rootScope.modalInstances.push($uibModal.open({
template: '<form id="form_popup" class="form-horizontal"><div class="modal-header">
<h3 class="modal-title"><button type="submit" class="btn btn-primary"
ng-click="fn_confirmar()">
OK</button></div></form>',
controller: function($scope){
$scope.fn_confirmar=function(){
oElim.fn_confirmar();
}
},
backdrop: 'static'
}));
}
oElim.fn_confirmar = function(){
var index = oElim.array.indexOf(oElim.objeto);
oElim.array.splice(index, 1);
popup_generico.fn_CerrarModal();
}
return oElim;
})
I do not believe that this is possible within angular, as the template is a string that will be interpolated within the context of the controller, not the factory.
If you really want to have scope access to the oElim factory without injecting it into a controller, you could bind the oElim object directly to the $rootScope, giving you prototypal access to its methods within the template "$rootScope.oElim.fn_confirmar()" or equivalently just "oElim.fn_confirmar()" from any template you define in your angular app.
As I know it's not possible, but you can do the following:
controller: function($scope){
$scope.fn_confirmar = oElim.fn_confirmar;
},
or add the object to $rootScope
.factory('eliminar', function($state,$rootScope,$uibModal,popup_generico) {
var oElim= {};
$rootScope.oElim = oElim;
oElim.fn_generarPopupConfirm = function(objeto,array,titulo,contenido) {
$rootScope.modalInstances.push($uibModal.open({
template: '<form id="form_popup" class="form-horizontal"><div class="modal-header">
<h3 class="modal-title"><button type="submit" class="btn btn-primary"
ng-click="oElim.fn_confirmar()">
OK</button></div></form>',
controller: Function.prototype, //Just dummy function
backdrop: 'static'
}));
}
oElim.fn_confirmar = function(){
var index = oElim.array.indexOf(oElim.objeto);
oElim.array.splice(index, 1);
popup_generico.fn_CerrarModal();
}
return oElim;
})
or better, just used built-in angular event service
.factory('eliminar', function($state,$rootScope,$uibModal,popup_generico) {
var oElim= {};
oElim.fn_generarPopupConfirm = function(objeto,array,titulo,contenido) {
$rootScope.modalInstances.push($uibModal.open({
template: '<form id="form_popup" class="form-horizontal"><div class="modal-header">
<h3 class="modal-title"><button type="submit" class="btn btn-primary"
ng-click="$emit('fn_confirmar')">
OK</button></div></form>',
controller: Function.prototype, //Just dummy function
backdrop: 'static'
}));
}
oElim.fn_confirmar = function(){
var index = oElim.array.indexOf(oElim.objeto);
oElim.array.splice(index, 1);
popup_generico.fn_CerrarModal();
}
$rootScope.$on('fn_confirmar', oElim.fn_confirmar);
return oElim;
})

Pass json value as ng-model value in angular 1.2

I'm trying to bind 2 separate elements so that one can trigger the other. The first step in this, is adding an identifying variable to my component template.
Here's the bullet.html template:
<div class="button bullet" ng-model="component.bullet.show_on_click" ng-click="showElementByUniqueName( component.bullet.show_on_click )"><p>{{component.bullet.text}}</p></div>
I'd like to know what is the correct syntax to set ng-model as the VALUE in component.bullet.show_on_click. At the moment, in the final html, ng-model turns out just as shown in the template. I have tried single speech marks and single AND double curly braces; All throw errors.
Any help, much appreciated!
EDIT
On request, here is some more detail:
The eng-bullet attribute fires up the engBullet directive:
app.directive('engBullet', function() {
return {
restrict: 'A',
replace: true,
templateUrl: 'components/bullet.html',
link: function(scope, element, attrs) {
// following function referenced in bullet.html
scope.showElementByUniqueName = function (showOnClick) {
// remove 'replaces' element
$('#'+$('#'+showOnClick).attr('data-replaces')).addClass('hidden');
// hide all popups (in case another popup is currently visible)
$('.popup').addClass("hidden");
// show selected popup
$('#'+showOnClick).removeClass("hidden");
}
}
};
});
The eng-popup attribute fires up the engPopup directive:
app.directive('engPopup', function() {
return {
restrict: 'A',
replace: true,
templateUrl: 'components/popup.html',
link: function(scope, element, attrs) {
scope.show = true;
scope.complete = false;
// watch for this popup being made visible and check if
scope.$watch(function() { return element.is(':visible') }, function() {
scope.$parent.componentCompleted(attrs.id);
});
}
};
});
..which loads in the components/popup.html template:
<div class="hidden popup {{component.popup.type}}" id="{{component.popup.name}}" data-replaces="{{component.popup.replaces}}" eng-completable ng-show="component.popup.name">
<div ng-if="component.popup.type=='overlay'">
<div class="float-right button close-button">X</div>
</div>
<p class="heading">{{component.popup.heading}}</p>
<div class="popup-content">
<div ng-if="0" ng-repeat-start="(innerIndex, component) in component.popup.popup_components"></div>
<div ng-if="0" ng-repeat-start="(type, object) in component"></div>
<div ng-attr-id="{{'p' + pageId + '-s' + skey + '-c' + ckey + '-component-' + index + '-innerComponent-' + innerIndex}}" ng-switch="type">
<div ng-switch-when="image" eng-image></div>
<div ng-switch-when="paragraph" eng-paragraph></div>
</div>
<div ng-if="0" ng-repeat-end></div>
<div ng-if="0" ng-repeat-end></div>
</div>
</div>
I'm not sure this is really relevant to the question though, which is how do I get the VALUE in component.bullet.show_on_click to present in the final html as the value of ng-model in the bullet html template, eg:
ng-model="unique_name_here"
?
Thanks.

Why is my angular binding read only in a bootstrap UI modal in an MVC5 project?

I am trying to pop up a modal to get some input, but the angular binding via ng-model seems to be read only. This is my modal markup:
<script type="text/ng-template" id="signatureWindow.html">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">Signature Capture</h4>
</div>
<input type="text" width="100px" ng-model="theName" />
<div class="modal-footer">
<button ng-click="accept()" class="btn btn-primary">Accept</button>
<button ng-click="cancel()" class="btn btn-default">Cancel</button>
</div>
</script>
Then, I invoke this modal as follows:
$scope.getSignatureModal = function(signatureBase64) {
var modalInstance = $modal.open({
templateUrl: 'signatureWindow.html',
controller: 'SignatureModalController',
size: 'lg',
resolve: {
signatureData: function() {
return signatureBase64;
}
}
});
modalInstance.result.then(function(signatureData) {
alert('Signed');
signatureBase64 = signatureData;
}, function() {
alert('Canceled');
});
};
And the following controller code for the modal:
MlamAngularApp.controller('SignatureModalController', function($scope, $modalInstance, signatureData) {
$scope.base64 = signatureData;
$scope.thename = "NamesRus";
$scope.accept = function() {
debugger;
$modalInstance.close($scope.thename);
}
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
}
});
The modal pops up as expected, and the input has the initial value "NamesRus", but when I close the modal, invoking accept in the modal controller, $scope.thename still has it's initial value, not any new value I type when the modal is active. What could be wrong here?
NOTE: At the debugger breakpoint in accept, no matter what I type in the modal's input, theName still has the initial assigned value.
MORE: My Plunker for this works fine. It's when in-place, in an ASP.NET MVC5 project, that I get the strange behaviour.
I think that you mix up two differents scopes.
If you want several variables to be passed to and retrieved from the modal you have to mention them:
in the resolve attribute
resolve: {modalData: function (){return {signatureData:$scope.base64,name:$scope.theName}}}
pass modalData as dependencie to your controller
MlamAngularApp.controller('SignatureModalController', function($scope, $modalInstance, modalData)
update the modal controller $scope with modalData
$scope.signatureData = modalData.signatureData;
$scope.name=modalData.name;
invoke
$modalInstance.close({signatureData:$scope.base64,name:$scope.theName})
reassign the original $scope with the result of promise
modalInstance.result.then(function (data) {
$scope.base64 = data.signatureData;
$scope.thename=data.name;
}
take a look at this plunker forked from ui-boostrap modal orginal example: http://plnkr.co/edit/whLSYt?p=info

Controller is not defined

I'm trying to use the Angularjs-UI Modal into my application and I'm a little confused as to what goes where. I have a button for new groups which calls a model, the models controller is in another file. I'm trying to call the newGroupCtrl within the groupCtrl but it's returning undefined.
HTML for new group button:
<button type="button" class="delGroupBtn" ng-click="newGroup()">New Group</button>
In my groupCtrl I have this newgroup() function:
$scope.newGroup = function (){
var modalForm = '/Style%20Library/projects/spDash/app/partials/newGroup.html';
var modalInstance = $modal.open({
templateUrl: modalForm,
backdrop: true,
windowClass: 'modal',
controller: newGroupCtrl,
resolve:{
newGroup:function (){
return $scope.newGroup;
}
}
});
};
Then I've got my newGroup.html (the modal) which is where the user would enter the groups name, description, owner:
<div class="modal-header">
<form>
<label for="groupName">Group Name:
<input id="groupName" type="text" ng-model='newGroup.name'>
</label>
<hr>
<label for="groupDesc">Group Description:
<input id="groupDesc" type="text" ng-model='newGroup.desc'>
</label>
<hr>
<label for="groupOwner">Group Name:
<select id="groupOwner" type="text" ng-model=''></select>
</label>
<div class="modal-footer">
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
<button class="btn primary-btn" type="button" ng-click="newGroup()">Create</button>
</div>
</form>
</div>
Here's the newGroupCtrl:
spApp.controller('newGroupCtrl',
function newGroupCtrl($scope, $modalInstance){
$scope.newGroup = {
name:null,
desc:null
};
$scope.submit = function(){
console.log('creating new group');
console.log(newGroup);
$modalInstance.dismiss('cancel');
}
$scope.cancel = function (){
$modalInstance.dismiss('cancel');
};
$modalInstance.result.then(function (){
groupService.newGroup($scope.newGroup);
}, function (){
console.log('No new group created.');
});
}
);
I've injected the group and newGroup controllers with my group service which is where I'm trying to get the information from the model to the groupService function to make the AJAX call to my server and create the new group. It seems like I'm repeating myself in both controllers with the $model.open({})
Here's a plunker
When controller is defined as part of the angular module (using .controller() method) than it must be referenced as a string.
When controller is defined as a simple JS function, then it must be referenced through a variable.
In you modal configuration object, you referenced newGroupCtrl as a variable, not as a string.
...
controller: newGroupCtrl,
...
vs
...
controller: 'newGroupCtrl',
...
But your controller is defined with angular.module().controller():
spApp.controller('newGroupCtrl',
function newGroupCtrl($scope, $modalInstance){...})
To fix, you need to put the name of the controller in quotes OR define the controller as a simple standalone JS function.
So, it's either this:
...
controller: 'newGroupCtrl',
...
spApp.controller('newGroupCtrl',
function newGroupCtrl($scope, $modalInstance){...})
OR this:
...
controller: newGroupCtrl,
...
function newGroupCtrl($scope, $modalInstance){...}

Categories

Resources