"As" Angular ng-controller not working as expected - angularjs

The doc makes me think that below, I should be using ng-click="ctrl.nextDay()" due to "GameController as ctrl". However, in that case, nothing happens and no errors are reported. Just ng-click="nextDay()" works though.
<div ng-controller="GameController as ctrl" >
<div class="panel panel-default">
<button type="button" class="btn btn-info" ng-click="nextDay()" >
<span class="glyphicon glyphicon-step-forward" aria-hidden="true">Next Day
</button>
</div>
The controller is defined as follows:
angular.module('FEModule')
.controller('GameController', ['$scope', '$http', '$fancyModal',
function($scope, $http, $fancyModal) {
console.log("GameController is instantiated! Yeah.");
$scope.nextDay = function() {
console.log("this is next day function!");
}
What is the reason for this?

nextDay() is a function of the $scope. So it's not attached to the controller, and is accessed in the view, like any other function on the scope, using nextDay().
If you want to make it a function attached to the controller, and thus use ctrl.nextDay() in the view, the code in the controller must be
this.nextDay = function() {
console.log("this is next day function!");
}

Bind nextDay() to the controller instance or remove controller as syntax and use $scope.
Solution A
<div ng-controller="GameController as ctrl" >
<div class="panel panel-default">
<button type="button" class="btn btn-info" ng-click="ctrl.nextDay()" >
<span class="glyphicon glyphicon-step-forward" aria-hidden="true">Next Day
</button>
</div>
Solution B
<div ng-controller="GameController" >
<div class="panel panel-default">
<button type="button" class="btn btn-info" ng-click="nextDay()" >
<span class="glyphicon glyphicon-step-forward" aria-hidden="true">Next Day
</button>
</div>

Related

How to enhance ngSanitize whitelists?

I'm trying to append HTML content from the controller to the view. For this I know that we have to use ngSanitize. Everything is working fine, but it is stripping out the attributes of the HTML elements.
Here is my controller:
var modalVar = '<div class="modal fade" id="deleteModal'+ data.data.id +'" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal">×</button><h4 class="modal-title">Alert</h4></div><div class="modal-body"><p>Are you sure to delete?</p></div><div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">Close</button><button type="button" class="btn btn-danger" ng-click="deleteFunc('+ data.data.id +')" data-dismiss="modal">Yes</button></div></div></div></div>';
$scope.modalsDiv = $scope.modalsDiv + modalVar;
The view:
<div ng-bind-html="modalsDiv"></div>
If I inspect and see the rendered elements, every div element is rendered but their attributes are stripped out.
Controllers should not be adding HTML to the view.
<!--REPLACE ng-html-bind
<div ng-bind-html="modalsDiv"></div>
-->
<!--WITH ng-if -->
<div ng-if="showModal">
<div class="modal fade" id="deleteModal{{data.data.id}} +'" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
×
</button>
<h4 class="modal-title">
Alert
</h4>
</div>
<div class="modal-body">
<p>Are you sure to delete?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
Close
</button>
<button type="button"
class="btn btn-danger"
ng-click="deleteFunc(data.data.id)"
data-dismiss="modal">
Yes
</button>
</div>
</div>
</div>
</div>
</div>
JS
//$scope.modalsDiv = modalVar;
$scope.showModal = true;
Instead of composing HTML in the controller, use the ng-if directive. The code will be much more readable.
try this in your controller:
someVar = $sce.trustAsHtml('someVar');
do not forget to inject $sce into ctrl

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();
}
}

Edit with bootstrap modal and AngularJS

I have made bootstrap modal for edit particular data from my data-table.
I am able to open popup and able to fetch my data as well, but as i am doing some changes in modal's text box it is suddenly reflect to data-table also (data-table is in another controller).
I want to reflect it in data-table only if I am clicking Update button.
And if I click cancel button then the previous value should be there.
Here is my HTML code:
<tr ng-repeat="Filterlist in macAddressListResult" class="text-center">
<td>{{1+$index}}</td>
<td class="padding-top-8">
<span class="label" >{{Filterlist.status}}</span>
</td>
<td><span>{{Filterlist.macAddress}}</span></td>
<td>
<button ng-click="openModal(Filterlist)" class="btn btn-xs btn-primary" title="Edit">
<i class="glyphicon glyphicon-edit"></i>
</button>
<button class="btn btn-xs btn-danger" title="Delete">
<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
Here is Modal HTML code:
<div class="modal-header bg-color">
<h3 class="modal-title">Edit</h3>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-2">
MacAddress
</div>
<div class="col-md-10">:
<input type="text" ng-model="mac.macAddress" name="macAddress" >
</div>
</div>
<br>
<div class="row">
<div class="col-md-2">
status
</div>
<div class="col-md-10">:
<select type="text" ng-model="mac.status" name="macAddress" >
<option ng-repeat="p in denyAllow">{{p}}</option>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-success" ng-click="ok(mac)"> Save </button>
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
</div>
Here is angularJS code:
app.controller('networkModeCtrl', function($rootScope, $scope, $state, networkModeService, $modal, $timeout){
$scope.openModal = function(mac){
var modalInstance = $modal.open({
templateUrl: 'partials/settings/macAddressEdit.html',
controller: 'macAddressEditCtrl',
controllerAs: 'vm',
scope: $scope,
resolve: {
mac: function () { return mac}
}
});
}
});
app.controller('macAddressEditCtrl', function($scope, $state, $stateParams, $modalInstance, mac, networkModeService, indexService){
$scope.mac = mac;
// === Get Mac address filter mode (allow/Deny) list === //
networkModeService.denyAllow().success(function(result){
$scope.denyAllow = result;
});
// === function to save mac staus ===//
$scope.ok = function(mac) {
$modalInstance.close();
};
// === function to cancel model === //
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
So, please anyone know me where I am going wrong!!!
Thanks in advance.
This is happening because of two-way data binding, which is the core feature of AngularJS.
When you pass the Filterlist object to the modal with scope set to $scope, you are effectively letting the modal communicate with the data in datatable directly, and updating it in real time.
To achieve your requirement, you should copy the Filterlist object like this in your controller:
$scope.updateFilterlist = angular.copy($scope.Filterlist);
And pass it to the modal:
<button ng-click="openModal(updateFilterlist)" class="btn btn-xs btn-primary" title="Edit">
<i class="glyphicon glyphicon-edit"></i>
</button>
Or do it directly in the view code:
<button ng-click="openModal(angular.copy(Filterlist))" class="btn btn-xs btn-primary" title="Edit">
<i class="glyphicon glyphicon-edit"></i>
</button>
This will create two different instances of the object in memory so that changes to one in the modal do not reflect on the other in the datatable.
You can then add code to copy the changes made to updatedFilterlist to Filterlist when 'Update' button is clicked.

ng-click directive not passing desired parameter

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);
}
}

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.

Resources