I have actionButtons
directive:
function actionButtons(){
'use strict';
return {
scope: {},
restrict: 'AE',
bindToController: {
itemId: '@',
itemDescription: '@',
actionsText: '@',
previewAction: '&',
previewText: '@',
editAction: '&',
editText: '@',
removeAction: '&',
removeText: '@'
},
controller: ActionButtonsController,
controllerAs: 'actionButtonsCtrl',
templateUrl: 'src/views/directives/actionButtons.html'
};
}
With ActionButtonsController
controller:
/**
*
* @constructor
*/
function ActionButtonsController() {
'use strict';
var viewModel = this;
//not important assertions
}
/**
*
* @type {boolean}
*/
viewModel.hasItemDescription = typeof viewModel.itemDescription === 'string' &&
viewModel.itemDescription.length > 0;
/**
*
* @type {string}
*/
viewModel.previewText = viewModel.previewText || 'preview';
/**
*
* @type {string}
*/
viewModel.editText = viewModel.editText || 'edit';
/**
*
* @type {string}
*/
viewModel.removeText = viewModel.removeText || 'remove';
/**
*
* @type {string}
*/
viewModel.actionsText = viewModel.actionsText || 'Actions';
viewModel.preview = function() {
viewModel.previewAction();
};
viewModel.edit = function() {
viewModel.editAction();
};
viewModel.remove = function() {
viewModel.removeAction();
};
}
And part of his template, with button:
<div class="visible-xs-block btn-group" data-dropdown>
<button class="btn btn-block btn-primary" id="{{::(actionButtonsCtrl.itemId)}}" type="button"
data-dropdown-toggle aria-haspopup="true">
{{actionButtonsCtrl.actionsText}} <span class="sr-only" data-ng-if="::actionButtonsCtrl.hasItemDescription">
for {{::(actionButtonsCtrl.itemDescription)}}</span></button>
</div>
And that is how I call it in application:
<td class="col-md-3 col-xs-3 text-center">
<div data-action-buttons
data-item-id="{{author.id + '_' + author.name + '_' + author.surname}}"
data-item-description="{{author.name + ' ' + author.surname}}"
data-preview-action="authorCtrl.preview(author)"
data-edit-action="authorCtrl.edit(author)"
data-remove-action="authorCtrl.remove(author)"
></div>
</td>
And the problems is: as you can see from controller code, for example actionsText
is not required, if is not present it will be set to Actions
. itemDescription
also is not required. But if I specify itemDescription
it is visible in HTML DOM all the time, but Actions
behaves in very strange way for me: it is set to default value Actions
, but it is not visible in HTML DOM. The difference between this two is that actionsText
is bound to this
in controller's code explicity - but I thought that is default behavior with bindToController
and this is what I should do when I want to set default value where value is not present. Also, when I debug it (for example by calling one of the function), actionsText
has undefined
value, despite the fact that if I debug it when it is created, it has set a default Actions
value. It doesn't work both with one-time binding (with ::
) and normal situations. Maybe it's something with scope: {}
from directive's code, but I can't figure it out and I hope for your help - thank you in advance. P.S. I tried return viewModel
variable from controller - it didn't help. P.S. 2 It works well if actionsText
is specified (as data-actions-text={{'Something'}}
)
You are using bindToController
which indirectly add the scope values to controller this
context. But this issue is happening because you are using @
symbol inside your bindToController
expression.
Whenever there is case with controllerAs
, bindToController
& scope with @
angular handle this thing in sightly different way.
Actually when you use @
on scope variable inside isolated scope with controllerAs
& bindToController
angular put a watch using $observe
on the expression given on that attribute
value, angular code for same
The solution would use $timeout
to do all assignment which are going to fetch using @
of isolated scope value. Because value gets bind in next digest cycle cycle after the $observe
expression gets evaluated.
Code
function ActionButtonsController() {
'use strict';
var viewModel = this;
$timeout(function() {
viewModel.hasItemDescription = typeof viewModel.itemDescription === 'string' &&
viewModel.itemDescription.length > 0;
viewModel.previewText = viewModel.previewText || 'preview';
viewModel.editText = viewModel.editText || 'edit';
viewModel.removeText = viewModel.removeText || 'remove';
viewModel.actionsText = viewModel.actionsText || 'Actions';
})
viewModel.preview = function() {
viewModel.previewAction();
};
viewModel.edit = function() {
viewModel.editAction();
};
viewModel.remove = function() {
viewModel.removeAction();
};
};
This is detailed version answer