In AngularJS, is it possible to pass the source element as a parameter in its ng-class attribute? - angularjs

Please, consider the following example for understanding my question:
<button ng-class="$scope.controllerMethod($thisButton)" />
In my controllerMethod, I want to get a reference of the button who called ng-class. Is it possible?
(Something like passing $event.target in the ng-click button, so I can read the caller from the controller).
Any helps? Thanks!!

If you're hard coding each of your button in your menu, you won't need ng-class. Simply ng-click=doSomething('$event'), then the rest is just like your normal Javascript, do whatever you want with $event.target.
If you want do it the angular way, each button needs to have a corresponding model in the controller.
<ul>
<li ng-repeat='btn in buttons'>
<button ng-class='{"highlight":btn.clicked}' ng-click='doSomething(btn)'></button>
</li>
</ul>
In your controller:
$scope.buttons = [{text:'button1'},{text:'button2'}];
$scope.doSomething = function(btn){
btn.clicked = true;
}
In this example, ng-class will watch each button's clicked property, if it's true, then add highlight class onto this button.

Related

Passing multiple 'button' parameters to Angular component

I'm creating a reusable item picker component using Angular 1.5. The picker has a search field and a list of items to choose from. An example use case for the picker is a popup where the user selects some items and then has a "Continue" button to proceed.
Conceptually, the search field and the list of items belong to the component and the "Continue" button belongs to the surrounding dialog. However, I want to position the button next to the search field. In some cases there are no extra buttons, sometimes one extra button, sometimes two.
Something like this:
What is the best way to create such a component?
Options I've thought of:
Create a component / directive for the item picker, put the button before or after the directive in the HTML, and use CSS to position the button.
Here the positioning of the button is ugly and fragile, as it's not in the proper position within the HTML. It would probably need a wrapper div and absolute positioning on top of the picker component:
<div style="position: relative">
<item-picker></item-picker>
<button name="Continue" ng-click="submit()" style="position:absolute; top:5px; right: 5px"></button>
</div>
Somehow pass the buttons and callbacks as parameters to the item picker component. Here the ugliness is in the hard-coding of the buttons and styles and amount of buttons:
<item-picker btn1-text="Continue" btn1-style="primary" btn1-callback="submit()" btn2-text="Cancel" btn2-style="secondary" btn2-callback="cancel()"></item-picker>
I'm unsure whether the button configuration and callbacks could be passed as a single configuration object. I'm mainly concerned about the callback functions, whether they will work properly if passed through a configuration object instead of proper '&' callback binding.
Stop trying to make the picker into a component / directive and just use <ng-include> to include the picker code which reads the button configuration from the scope. Ugliness is in lack of scoping and not using components.
Is there some best practise for such cases?
One possible solution is to use ng-transclude, so your code could look something like:
Markup
<item-picker>
<button ng-click="parentScopeFn()">Btn 1</button>
...
</item-picker>
Directive
angular.module('myApp', [])
.directive('itemPicker', function() {
return {
restrict: 'E',
transclude: true,
scope: {
...
},
templateUrl: 'item-picker.html'
};
});
itemPicker template markup
<div class="item-picker">
<div class="item-picker-controls">
<div class="item-picker-search"><input type="search" ng-model="..."></div>
<div class="btn-group" ng-transclude></div>
</div>
<ul class="item-picker-list">
<li ng-repeat="item in items" ng-bind="item"></li>
</ul>
</div><!-- end item-picker template -->
Of course the above code is just an example and is making a lot of assumptions about your itemPicker component. Also, you'll still need to use CSS to position your buttons, but it might be easier to reason with b/c it'll be in the context of your component.
Note
You could also make use of "multi slot transclusion". This is probably useful in cases where the number and type of buttons you'll have is predictable and you want them arranged in a consistent way no matter how they are placed in the markup.
Hope this helps.

ngDialog - how to close dialog from the template (i.e. no controller functions)?

On ngDialog (https://github.com/likeastore/ngDialog), is there a built in way to close a dialog from within the template it self? I.e. so I don't need any functions in the controller calling the dialog?
This is my template (errorPopup.html):
<div>
<div class="alert alert-warning">
<div class="errorLogo"><i class="icon-exclaim"></i></div>
<div class="errorContent" data-ng-bind-html="errorMessage"></div>
</div>
<div class="buttonWrapper">
<button type="button" class="btn-primary pull-right">
<span res="close"></span>
</button>
</div>
</div>
And this is how I open the dialog:
function showErrorPopup() {
ngDialog.open({
template: 'errorPopup.html',
scope: $scope,
className: 'ngdialog-theme-default ngdialog-cart-theme',
showClose: true,
appendTo: 'div[ui-view]',
closeByDocument: false
});
}
So when I call showErrorPopup() I get a dialog displayed, however, I need to make this "close" button to actually dismiss/close the popup. As of now, this is just a plan button that doesn't do anything.
Is there something I can do a the template level (without changing my controller's code) to make the button work?
Maybe I should be using a default button instead of my own? If so, how?
PS: I notice thats clicking on the X button on the top right works, the popup is dismissed.
Thanks all!
You don`t have to inject ngDialog module in your $scope. You can call closeThisDialog() function in your popup template directly:
<button ng-click="closeThisDialog(0)">Close</button>
function argument is the value to resolve popup with.
If you want to call the close function of the ngDialog directly from the view, you must inject the module itself to the scope inside the controller, in order for it to become available from the view:
$scope.ngDialog = ngDialog;
Then, you can use it directly from within the view:
<button ng-click="ngDialog.close()">Close</button>
It is hard to say what exactly you are doing wrong, until you paste some controller and app.js and HTML code contents.
Yes, ngDialog has built-in way of closing the dialog
Make Sure you set the className to 'ngdialog-theme-flat ngdialog-theme-custom' or other css class as described in the docs inside open function.
You have added handler with name "closeThisDialog" , but function has another name "closePopup".
Maybe it is your issue.
just follow these steps
1.when creating app
var app = angular.module('sampleApp', ['ngDialog']);
2.use button like this
<button ng-click="clickMe()">Click to Open</button>
3.put this in your controller
`$scope.clickMe = function () {
ngDialog.open();
};`
by default it has code to close,It'll close automatically when you click on close.
Hope it'll be useful

Angular- Getting closest element on mouseover

I'm new to Angular JS and i'm trying to create a small web app for learning.. I am trying to make a Tooltip text on mouseover but i'm not sure how to get it done the "Angular way"..
I created 2 spans, when hovering the first, i want to show the second
I tried using ng-mouseover and ng-mouseleave to call the actions-
<span class="info" ng-mouseover="info_in();" ng-mouseleave="info_out();">
<img src="images/info.png" />
</span>
<span class="info_bubble" ng-show="info">The Tooltip Text</span>
And that's where i got with the JS-
$scope.info_in = function() {
this.parent().find('.info_bubble') = true;
};
$scope.info_out = function() {
this.parent().find('.info_bubble') = false;
};
There are going to be more than 1 Tooltip text on each page and i'm not sure how to get it done.. I tried with "next()" and "closest()" but couldn't get it to work
When i try to mouseover the element, i get "this is not a function"
You've got the right idea but your implementation is moving toward the jQuery way, not the Angular way. :)
Try this:
<span class="info" ng-mouseover="info=true" ng-mouseleave="info=false">
<img src="images/info.png" />
</span>
<span class="info_bubble" ng-show="info">The Tooltip Text</span>
No controller code is necessary for this to work.
What you're doing is that when the mouse enters the image, Angular will set $scope.info to true. And since your tooltip is watching that scope variable, it will trigger the ng-show directive to fire which will show your tooltip.
The ng-show directive can be translated as: When $scope.info == true, then show() this element. When $scope.info == false, then hide() this element.
In fact, you could be more verbose (which is good for learning) writing your tooltip element like this:
<span class="info_bubble" ng-show="info==true">The Tooltip Text</span>
I notice that you're using the jQuery method of specifically trying to find an element in the DOM in order to work with it.
The Angular way is to change variables on the $scope. Other HTML elements will monitor variables on the $scope and will automatically change themselves depending on what the new value is. The jQuery way is to reach out and specifically touch and set a value on a DOM element. The Angular way is akin to shouting to the wind, "Hey, my name is $scope.info and I'm now true!" and expecting that some other element will hear it and go, "Ok cool, now I can show myself because $scope.info is true."
That's the main difference between the way jQuery and Angular work.

Adding modal when clicking a hyperlink

I want to load a modal using custom directive when a hyperlink is clicked. but the thing is that hyperlink already defined a ng-click function. Current ng-click function also should work my requirement. How can I do it without changing the ng-click function? Below is my hyperlink.
<a href="#" class="book-btns add-to-cart" data-ng-click="service.addToCart(hotel)" >Add to cart & Continue> </a>
href="javascript:;" should work to disable the default link behaviour.
Create the custom directive so that it binds to "click" on the element.

Rending a Modal in AngularJS

I'm attempting to learn AngularJS (background in BackboneJS). I have a div with some content inside, and I hope to render this div as a modal upon clicking inside of it:
<div class="stickynote"> Content here </div>
My thinking is to add a modal class that I can style in CSS. However, I'm not too sure how to add the modal class upon clicking (and conversely, removing the modal class upon clicking after the modal is rendered). Would I have to use ng-click and somehow set the class property from the JavaScript (myApp.js) file?
If you want to use your own modal styling and if you simply want to achieve adding an extra item to class attribute of your element, you can use a combination of ng-class and ng-click:
<div class="stickynote"
ng-class="{yourModalCSSClass: isModalOpen}"
ng-click="isModalOpen = true">
And somewhere else, you need another ng-click to turn it off:
<button ng-click="isModalOpen = false">Close modal</button>
Beware that both div and button must be in the same scope hierarchy to be able to use the same isModalOpen value. And by the way, I haven't tried this code but this should give you an idea. If you have a controller/directive, you can set isModalOpen from there by introducing functions in the scope:
// controller
$scope.toggleModal = function () {
$scope.isModalOpen = !$scope.isModalOpen;
}
<div ...
ng-click="toggleModal()">
<button ng-click="toggleModal()">...
If you're open to using a third-party solution, ng-dialog is an outstanding solution for modals+Angular.
https://github.com/likeastore/ngDialog

Resources