Can't access controllers scope from template that is loaded by ngBootBox
I can't resolve issue. Tried to use service and directive with custom dialog. Problem is that i cant acces Controller's $scope form template.
At example, if i will create $scope.model { param: 'value' } and will try to access it from ngbootbox loaded template, it will be null. I also tried to add $parent.model.param but stil cant access. Also I can't validate form in template. Everything works only if I specify in controller $rootScope everywhere instead of $scope.
My sample Code:
Controller:
angular.module('app.transfers')
.controller('MyController', function ($scope, $rootScope, $ngBootbox) {
$scope.model = {
param: 'some value'
};
$scope.transferDialogButtons = {
success: {
label: 'Cancel',
className: 'btn-default',
callback: function(result) {
return true;
}
},
main: {
label: 'Confirm',
className: 'btn-danger',
callback: function() {
return $scope.executeAction();
}
}
};
$scope.executeAction = function () {
$rootScope.$broadcast('show-errors-check-validity'); // form validation works only if $rootScope is specified
};
});
Html
<button class="btn btn-primary"
ng-bootbox-title="Title"
ng-bootbox-custom-dialog
ng-bootbox-custom-dialog-template="views/transfers/_partials/dialog.html"
ng-bootbox-buttons="transferDialogButtons">
<i class="fa fa-exchange"></i> Button Title
</button>
Template
<form class="form-horizontal" name="sampleForm" role="form" novalidate>
<div class="form-group" show-errors>
<label for="param" class="col-sm-4 control-label">Param:</label>
<div class="col-sm-8">
<input ng-model="model.param" name="param" type="text" class="form-control" required>
<p class="help-block" ng-show="sampleForm.destination.$error.required">Error Message 1</p>
</div>
</div>
</form>
Hi,
In new version there is options to add scope to custom dialog using ng-bootbox-options directive. But it is not documented yet.
<button class="btn btn-primary"
ng-bootbox-title="Title"
ng-bootbox-custom-dialog
ng-bootbox-custom-dialog-template="views/transfers/_partials/dialog.html"
ng-bootbox-options="dialogOptions">
<i class="fa fa-exchange"></i> Button Title
</button>
Controller:
angular.module('app.transfers')
.controller('MyController', function ($scope, $rootScope, $ngBootbox) {
// your staff
$scope.dialogOptions= {
scope: $scope,
buttons: {
success: {
label: 'Cancel',
className: 'btn-default',
callback: function(result) {
return true;
}
},
main: {
label: 'Confirm',
className: 'btn-danger',
callback: function() {
return $scope.executeAction();
}
}
}
};
// your stuff
});
Note: I move your buttons to options (make setup on one place). Could you test it with this setup?
@vlapo Thanks for fast reply. Now I can access to scope variables. Everything works except I can't load array of data into ui-select which is located in template that is loaded by ng-bootbox.
If i place this code into template:
<ui-select ng-model="model.wallet" theme="bootstrap" class="ui-select">
<ui-select-match placeholder="Select Wallet">{{ $select.selected.full_name }}</ui-select-match>
<ui-select-choices repeat="wallet in wallets | filter: $select.search">
<div ng-bind-html="wallet.full_name | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
Choices doesn't load into ui-select, but if I place same code into my html, below ngbootbox modal button, which is in one scope with controller, then choices are loaded into ui-select.
Controller code:
$scope.model = { wallet: null };
$scope.wallets = null;
WalletService.getResource().get({ }, function (response) {
$scope.wallets = response.data.wallets;
});
I think it is because dialog body is compile with your scope only on creation of dialog.
So your $scope.wallets are fill with data async (response from server) and new value of wallets is not reflected in template.
I have this issue before and I take out this functionality to separate controller.
Template
<div ng-controller="MyDialogController" ng-init="initWallets()">
<ui-select ng-model="model.wallet" theme="bootstrap" class="ui-select">
<ui-select-match placeholder="Select Wallet">{{ $select.selected.full_name }}</ui-select-match>
<ui-select-choices repeat="wallet in wallets | filter: $select.search">
<div ng-bind-html="wallet.full_name | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
</div>
Controller
angular.module('app.transfers')
.controller('MyDialogController', function ($scope, WalletService) {
$scope.wallets = null;
$scope.initWallets = function() {
WalletService.getResource().get({ }, function (response) {
$scope.wallets = response.data.wallets;
});
}
});
Try this way :)
@reinos, @eriktufvesson - What do you think about this issue? I dont have experience with $compile and there is question if $scope changes have to be reflected after dialog creation.
@ddctd143 Maybe this will work:
$scope.model = { wallet: null };
$scope.wallets = WalletService.getResource().get({});
But I don know. It is only idea :) Feel free to try it.
@vlapo Is there a way to disable ngbootbox main button while callback function is running, because if main button fires callback function, it still can be pressed many times before dialog is closed.
main: {
label: 'Submit',
className: 'btn-danger',
callback: function() {
return $scope.doSomething();
}
}
How I could access button's html to add custom data params ? If i had access to button, I could add bootstrap's data-loading-text and btn-loading="loadingState" to lock button while callback is running.
Maybe this question isn't releated to ng-bootbox, but I'm new to angular
Do you resolve issue before (if yes, which solution)?
I dont have info about functionality like this. Maybe new feature request.
In custom dialogs I always use my own buttons in template because I like to control all in dialog (and use $ngBootbox.hideAll() to close dialog) :)
@vlapo I also use custom dialog with custom buttons. Consider this example:
main button in ng-bootbox-dialog fires callback $scope.serverCallback() which sends something to server. While callback is sending ngbootbox dialog will be opened, and user can click many times to button and fire same function again and again. How do you lock submit button, while callback is running ?
$scope.transferDialogOptions = {
scope: $scope,
buttons: {
main: {
label: 'Submit Dialog',
className: 'btn-danger',
callback: function() {
return $scope.serverCallback();
}
}
}
};
$scope.serverCallback = function() {
if ($scope.form.$valid) {
$scope.submitLoadingState = true;
SomeService.store($scope.model, function (transfer) {
// While this function is running ( sending something to server... )
// Dialog will be opened, and "Submit Dialog" can be pressed many times
return true; // Closes dialog
});
}
return false;
};
How to resolve this issue ?
Could you answer the first question please?
You dont understand :) I dont use buttons option. I have own buttons in dialog template.
E.g. dialog tepmplate
<div ng-controller="MyDialogController" ng-init="initDialog()">
<form ng-submit="submitFunc()">
<!-- som form inputs and so on -->
<input type="submit" value="Submit" />
<button type="cancel" ng-click="cancelFunc()">Cancel</button>
</form>
</div>
MyDialogController
angular.module('app.transfers')
.controller('MyDialogController', function ($scope, $ngBootbox) {
$scope.initDialog= function() {
//some stuff
}
$scope.cancelFunc= function() {
//close dialog
$ngBootbox.hideAll();
}
$scope.submitFunc= function() {
//some stuff
// on success submit close bootbox dialog
$ngBootbox.hideAll();
}
});
This is little bit more stackoverflow discusion :) not github issue.
Thanks, will dig into it.
I have same problem. I get response from server and try to change the $scope but it doesnt works - it changes but right after the $scope keeps reverting to old value.
Update: Ok now it works. I needed to use $watch and window.localStorage
I solved in this way on the callback function:
.... callback : function(){ $scope.$apply(function(){ ///$scope.val1 = val2; }); }