ng-click directive not passing desired parameter - angularjs

I have the following piece of angular code: (it's a modal-popover menu which uses the following js library: http://scruffles.github.io/BootstrapModalPopover/).
<div ng-repeat="purchasedItem in purchased" class="row item_summary">
<!-- edited for brevity -->
<div id="{{purchasedItem.code}}-popover" data-product-id="{{purchasedItem.code}}" class="popover" style="display: none;">
<div class="arrow"></div>
<h3 class="popover-title" style="display: none;"></h3>
<div class="popover-content">
<div class='popover-menu-left'>
<button class="btn btn-sm btn-danger" ng-click='purchasedItems.removePurchasedItem(purchasedItem)'>Verwijderen</button><br>
</div>
<div class='popover-menu-right-template'>
<div class='number-content' style="display: none;">
<div ng-controller="numpadCtrl as numpad" class="numpad">
<!-- edited for brevity -->
<input type="button" class="btn btn-sm" value="enter" data-item-id='{{purchasedItem.code}}' ng-click="numpad.flushNumber(purchasedItem.code)"></input>
</div>
</div>
</div>
<div class='popover-menu-right-content'>
</div>
</div>
</div>
</div>
the problem lies with this particular piece of code:
<input type="button" class="btn btn-sm" value="enter" data-item-id='{{purchasedItem.code}}' ng-click="numpad.flushNumber(purchasedItem.code)"></input>
The data-item-id attribute was added just to see if I could get retrieve the code - this works just fine! But when I set a breakpoint in the flushNumber function, the parameter passed is undefined.
The code for the numpad controller is the following (it doesn't really do anything yet)
sportOaseControllers.controller('numpadCtrl', ['$scope',
function($scope) {
var parent = this;
parent.currentEntry = "";
parent.addNumber = function (number) {
parent.currentEntry = parent.currentEntry.concat(number);
console.log(parent.currentEntry);
};
parent.cancel = function() {
console.log('cancelled!');
parent.currentEntry = "";
};
parent.flushNumber = function(code) {
console.log('flushing!' + code);
}
}]);
The only thing which might be a clue is that the $scope injected into the numpad controller is null - my knowledge of angular is too minimal to do any real debugging however. Can somebody point me in the right direction?

This is a working JSFiddle, what AngularJS version do you have?
controller as was introduce since 1.2 it's not available before that.
HMTL:
<div ng-app ng-controller="FirstCtrl">
{{purchasedItem}}
<div ng-controller="numpadCtrl as numpad" class="numpad">
<!-- edited for brevity -->
<input type="button" class="btn btn-sm" value="enter" data-item-id='{{purchasedItem.code}}' ng-click="numpad.flushNumber(purchasedItem.code)"></input>
</div>
</div>
JS:
function FirstCtrl($scope) {
$scope.purchasedItem = {
code: 'hello'
};
}
function numpadCtrl($scope) {
this.flushNumber = function (code) {
console.log(code);
}
}

Related

x-editable nested editable-select not submitting

I have a editable-select nested inside other, when I submit the nested editable-select changes, it does not call the onaftersave assigned function ('vm.addOperation()'), it also shows the outter editable-select edit form.
I want it just to show the nested edit form and the function call to work.
My html code:
<div editable-select="vm.selectedUser"
e-ng-options="user.objectId as user.displayName for user in vm.users"
onshow="vm.getUsers()"
onaftersave="vm.addUser()">
<div class="container" ng-repeat="u in entity.authorizedUsers">
<div class="row">
<div class="col-xs-2">
{{u.id}}
</div>
<div class="col-xs-4">
<div editable-select="vm.selectedOperation"
e-ng-options="operation.id as operation.name for operation in vm.operations"
onshow="vm.getOperations()"
onaftersave="vm.addOperation()">
<div class="container" ng-repeat="op in u.authorizedOperations">
<div class="row">
<div class="col-xs-3">
{{op.name}}
</div>
<div class="col-xs-push-2">
<button class="btn btn-xs btn-danger"
ng-click="vm.removeOperation(entity.id, u.id, op.id)">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-push-4">
<button class="btn btn-xs btn-warning pull-left"
ng-click="vm.removeuser(entity.id, u.id)">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
</div>
</div>
I've manage to fix the problem with the following code. It's an ugly workaround tho, please if someone has a more elegant solution I'd very much appreciate it.
in html:
<div editable-select="vm.selectedOperation"
e-form ="nestedForm"
onshow="vm.getOperations()"
ng-click="nestedForm.$show(); vm.xEditableNestedFormFix(nestedForm); $event.stopPropagation()"
e-ng-options="operation.id as operation.name for operation in vm.operations"
onaftersave="vm.addOperation()">
in js:
vm.xEditableNestedFormFix = function (form) {
var editorElement = form.$editables[0].controlsEl[0].firstChild;
editorElement.onclick = function (event) {
event.stopPropagation();
}
var submitButton = form.$editables[0].buttonsEl[0].firstChild
submitButton.onclick = function (event) {
form.$submit();
event.stopPropagation();
}
var cancelButton = form.$editables[0].buttonsEl[0].lastChild
cancelButton.onclick = function (event) {
event.stopPropagation();
}
}

Angularjs error when i try remove button and append a new?

I have follow.js:
'user strict';
var SaurioApp = angular.module('SaurioApp', []);
SaurioApp.controller('SearchCtrl', function($scope, $http){
$scope.followUser = function(user_id,follow_to_id){
$http.get('ajax/follow', {
params: {user_id: user_id,follow_to_id: follow_to_id}
}).success(function(data){
$scope.unfollow = '<button class="btn btn-danger" ng- click="followUser({{Auth::user()->id}},{{$user->id}})">Seguir</button>';
});
}
});
and the view in blade
<div class="row" ng-app="SaurioApp">
<div class="col-xs-12 col-sm-12 col-md-12" >
<p ng-controller="SearchCtrl" >
#{{ unfollow }}
<button class="btn btn-primary" ng-click="followUser({{Auth::user()->id}},{{$user->id}})">Follow</button>
</p>
</div>
</div>
The insert is successful, but I can't delete the "Follow" button and append the new one: "Unfollow." How can I make this work?
<div class="row" ng-app="SaurioApp">
<div class="col-xs-12 col-sm-12 col-md-12" >
<p ng-controller="SearchCtrl" >
<button ng-show='unfollow' class="btn btn-danger" ng-click="followUser({{Auth::user()->id}},{{$user->id}})">Seguir</button>
<button ng-hide='unfollow' class="btn btn-primary" ng-click="followUser({{Auth::user()->id}},{{$user->id}})">Follow</button>
</p>
</div>
</div>
Similar to what #redoc says but with two buttons, one for unfollow and one for follow
SaurioApp.controller('SearchCtrl', function($scope, $http){
$scope.followUser = function(user_id,follow_to_id){
$http.get('ajax/follow', {
params: {user_id: user_id,follow_to_id: follow_to_id}
}).success(function(data){
$scope.unfollow = true;
});
}
});
It seems as if the only changes needed to be made are the CSS class and button text so in this case instead of trying to send HTMl code through the scope just send a variable and use ng-class to make the switch. Something like this:
'user strict';
var SaurioApp = angular.module('SaurioApp', []);
SaurioApp.controller('SearchCtrl', function($scope, $http){
$scope.followUser = function(user_id,follow_to_id){
$scope.unfollow=false;
$http.get('ajax/follow', {
params: {user_id: user_id,follow_to_id: follow_to_id}
}).success(function(data){
$scope.unfollow = true;
});
}
});
<div class="row" ng-app="SaurioApp">
<div class="col-xs-12 col-sm-12 col-md-12" >
<p ng-controller="SearchCtrl" >
#{{ unfollow }}
<button ng-class="{btn-danger: unfollow=false }" ng-click="followUser({{Auth::user()->id}},{{$user->id}})">Follow</button>
</p>
</div>
</div>
You can also change the button text dynamically with something like this:
<button value="{{(unfollow=false)? 'Follow' : 'Seguir'}}" ng-class="{btn-danger: unfollow=false }" ng-click="followUser({{Auth::user()->id}},{{$user->id}})"></button>
I guess the point being there is no need to actually recreate the HTML code just change the elements.

Using ng-click inside np-repeat

I'm trying to implement a shortlisting functionality in a case where I'm using ng-click inside ng-repeat.
While the $index is being displayed correctly outside the ng-click, $index is only the index of the last object in the JSON array in all the cases where the html is generated using ng-repeat.
I was expecting the respective venue or venue.id to be passed as an argument to shortlistThis(). I'm guessing that this could be an issue related to event binding.
Can someone help me understand what's going wrong here and probably a better way to do this if possible.
I did try checking this Bind ng-model name and ng-click inside ng-repeat in angularjs The fiddle here works just fine but, mine doesn't.
Update: I've found something interesting here. When the shortlist button is placed just under the ng-repeat, it work just as intended. But when, nested inside a div with a ng-class, it isn't working as intended. Can anyone explain and suggest a fix for this ?
//locationsapp.js var locationsApp = angular.module('locationsApp', []);
var venues = [{
id: "Flknm",
name: "ship",
}, {
id: "lelp",
name: "boat",
}, {
id: "myp",
name: "yacht",
}, ];
var shortlistedVenues = [];
var locationsApp = angular.module('locationsApp', ['ui.bootstrap']);
locationsApp.controller("getvenues", function($scope) {
$scope.venues = venues;
$scope.shortlistThis = function(venue) {
console.log(venue);
if (shortlistedVenues.indexOf(venue) == -1) {
shortlistedVenues.push(venue);
//alert('If');
} else {
console.log('already shortlisted')
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="locations" ng-app="locationsApp">
<div ng-controller="getvenues">
<div ng-repeat="venue in venues" ng-mouseover="" class="venue">
<div ng-controller="manageInfo">
<div class="row-fluid">
<div class="control" ng-click="showInfo()">
</div>
<div class="maps" class="info">
<div ng-class="class">
<div class="close-info" ng-click="hideInfo()">
<i class="fa fa-times">
</i>
</div>
<div class="row full-venue-contents" ng-app="ui.bootstrap.demo">
<div class="">
<div class="row-fluid myclass">
<div class="button-holder">
<div class="row-fluid">
<div class="col-md-4 col-xs-4 text-center btn-grid">
<button type="button" class="btn btn-default btn-lg btn-sup" ng-click="shortlistThis(venue)">
Shortlist{{$index}}
</button>
</div>
</div>
</div>
</div>
</div>
<!-- End of Full Info Container -->
</div>
</div>
</div>
</div>
<div class="compare">
<button type="button" class="btn btn-default btn-lg btn-sup">
Compare ( {{shortlistedVenues.length}} )
</button>
</div>
</div>
</div>
</div>
</div>
The problem is with your button div which was position: fixed, it is actually showing the 1st button but clicking on it firing last button click, I'd suggest you should suggest you render only the shortlist button which has been selected by you. For that you can use ng-if and render those button which index is the same as that of selected $index
HTML
<div ng-if="selected==$index" class="button-holder">
<div class="row-fluid">
<div class="col-md-4 col-xs-4 text-center btn-grid">
<button type="button" class="btn btn-default btn-lg btn-sup"
ng-click="shortlistThis($parent.$index)">Shortlist{{$index}}</button>
</div>
</div>
</div>
& then put ng-click="selected='$index'" on ng-repeat div like
<div ng-repeat="venue in venues" class="venue" ng-click="selected=$index">
Working Fiddle
Hope this could help you, Thanks.

How do I set the ui.bootstrap collapse feature to collapsed on page load?

I'm using ui.bootstrap and I'm trying to use the collapse function.
In my code what's happening is the default state is expanded, when the load weather button is clicked the div is collapsed and after the data has been loaded it expands.
What do I need to do to my code to get it to have a collapsed state on page load and only expand/contract when the button has been clicked?
Here's my code:
<div ng-controller="weatherCtrl">
<div>
<button ng-model="hotel" class="btn btn-default"
ng-click="loadWeather(hotel); isCollapsed = !isCollapsed">load weather</button>
<hr>
<div collapse="isCollapsed">
<div class="well well-lg">Some content</div>
</div>
</div>
</div>
.controller('weatherCtrl', function ($scope, weather) {
$scope.loadWeather = function (hotel) {
console.log('loadWeather')
console.log('hotel')
console.log(hotel)
weather.get({}, function (data) {
console.log('data')
console.log(data)
$scope.isCollapsed = false;
})
}
})
I got it working by using ng-init on a parent element:
<div ng-controller="weatherCtrl" ng-init="isCollapsed = !isCollapsed">
<div>
<button ng-model="hotel" class="btn btn-default"
ng-click="loadWeather(hotel)">load weather</button>
<hr>
<div collapse="isCollapsed">
<div class="well well-lg">Some content</div>
</div>
</div>
</div>

ng-click not executing controller function

I have a very simple function in one of my angular controllers
$scope.search = function () {
alert("Search");
};
and from my view I have
<button type="button" data-ng-click="search()"><i class="fa fa-search"></i></button>
The function is never executed when the button is clicked, but the rest of the code in my controller is executed as expected. Is there any reason why the ng-click directive will not fire my function?
I have similar controllers all working as expected.
Update
The button is within a bootstrap 3 modal, when the button is moved out of the modal, the click event works. Any reason for this happening?
Update
The button is within scope of the controller, here is my controller and view for clarity
(function () {
var module = angular.module("crest");
var brokerGridController = function ($scope, readEndpoint, readBroker) {
$scope.endpoint = "";
$scope.isBusy = false;
$scope.havebroker = false;
$scope.brokers = [];
$scope.searchCriteria = "";
$scope.exception = "";
var setEndpoint = function (response) {
$scope.endpoint = response.Endpoint;
};
readEndpoint.read("BusinessLogicAPI").then(setEndpoint);
var onSuccess = function (response) {
if (response.Message.MessageType == 1) {
onError();
}
$scope.havebrokers = response.brokers.length > 0;
angular.copy(response.brokers, $scope.brokers);
angular.copy(response.Message.body, $scope.exception);
};
var onError = function () {
$("#errorMessageModal").modal("show");
};
$scope.search = function () {
alert("Search");
};
};
module.controller("brokerGridController", ["$scope", "readEndpoint", "readBroker", brokerGridController]);
}());
and the view
<div data-ng-controller="brokerGridController">
<div>
<div class="col-md-4">
<div class="contacts">
<div class="form-group multiple-form-group input-group">
<div id="searchBrokerDropdown" class="input-group-btn input-group-select">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="concept">Broker Name</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>Broker Name</li>
</ul>
<input type="hidden" class="input-group-select-val" name="contacts['type'][]" value="phone">
</div>
<input type="text" name="contacts['value'][]" class="form-control" data-ng-model="searchPhrase">
<span class="input-group-btn searchButton">
<button type="button" class="btn btn-success btn-add" data-ng-click="$parent.search()"><i class="fa fa-search"></i></button>
</span>
</div>
</div>
</div>
</div>
<div>
<div class="col-md-12">
#Html.Partial("_Loading", new LoadingViewModel() { DisplayText = "Loading brokers..." })
<div data-ng-show="!isBusy && !haveBrokers">
<h3>No brokers found.</h3>
</div>
<div class="panel" data-ng-show="!isBusy && haveBrokers">
<div class="panel-heading">
<h4 class="panel-title">Brokers</h4>
<div class="pull-right">
<span class="clickable filter" data-toggle="tooltip" title="Filter Brokers" data-container="body">
<i class="fa fa-filter"></i>
</span>
</div>
</div>
<div class="panel-body">
<input type="text" class="form-control" id="task-table-filter" data-action="filter" data-filters="#task-table" placeholder="Filter Tasks" />
</div>
<table class="table table-hover" id="task-table">
<thead>
<tr>
<th>Broker Name</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="broker in brokers">
<td>{{ broker.Name }}</td>
<td data-ng-show="searchCriteria != 'PolicyNumberLike'"><i class="fa fa-search"></i> View Policies</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
You have to check 2 things in that situation:
Check if your button is in the front (rise his z-index or check is :hover is working), maybe it is not on top so it can't be clickable.
Check if that buttont dont have own $scope (it is crated in subdirective, or in ng-repeat for example), in taht situation check:
<button type="button" data-ng-click="$parent.search()"><i class="fa fa-search"></i></button>
If that 2 things dosen't work check if any command ex. console.log('test_mode') will fire after click.
It's most likely that the button is outside of controller scope, if you provide model with a specific controller you should put search function inside said controller, if you want to keep it in parent controller specify it like this:
$scope.modalFunctions = {
search: function () {
//do something
}
}
then use ng-click="modalFunctions.search"
Ok, I finally found the problem. My angular view is within a bootstrap wizard component (within a bootstrap modal) that I copied from Bootsnipp. The problem was with the javascript that was supplied,
wizardContent.html(currStep.html());
this piece of code replaced the wizard content with the HTML of the correct step. I modified the javascript to hide and show the correct steps instead of copying the HTML of the correct step to the div displayed to the user, which resolved the issue.

Resources