Suggestions for coding an ContextMenu with AngularJS - angularjs

I want to code a contextmenu directive for my project. First of all created a sample context menu as an angular JS directive:
var myApp = angular.module('myApp',[]);
myApp.directive("myContextMenu", function(){
restrict: 'AE',
replace: true,
template: "",
link: (scope, elem, attrs) ->
elem.bind "contextmenu", ->
scope.$apply ->
console.log "Right click to an item."
elem.bind "mouseleave", ->
elem.bind 'mouseover', ->
elem.css('cursor', 'pointer');
});
Here is my sample HTML file:
<div ng-app>
<div my-context-menu>
Right click to display a context-menu
</div>
</div>
When I right click to the text, I want to append some div(for ex. Sample Context Menu). When the mouse leaves the div I want the Sample Context Menu to be removed.
What is the right approach for that. Should I fill the "template" field of the directive? Should I hide and show the context menu? Or should I add and remove the context menu?
Any kind of help is kindly appreciated?
Regards.

Have a look at this project https://github.com/ianwalter/ng-context-menu
In my opinion the important thing is how you define the context menu and good example to think about it is ng-repeat (this way you will have to think about scope a bit more)
I think that defining menu inline would be quite clean
i.e
<my-context-menu>
<ul>
<li>
<a ng-click="f()">Option 1</a>
</li>
<li>
<a ng-click="f()">Option 2</a>
</li>
</ul>
</my-context-menu>
this way directive would be concerned only how the menu is displayed and the content would be defined inline and you could easily call function in current scope
I find showing / hiding div would good enough - maybe when u have huge number of items in page and different context menus creating div on the fly would be more suitable

I would use a more generic approach and make reusable to various controllers. Think about configurable option for adding items to menus. What methods would be called by clicking that item - make this also customizable.
Also the positioning of context menu, if menu oepned at right corner and gets hidden within window - have detection at place to shift the menu to left.
You can check the one I have written - https://github.com/shekhardesigner/Context-Menu-Angular-Directive

Related

In Angular, Is it possible to have one trigger for a tooltip to appear, and another for it to disappear?

So I have a button on my template, with a tooltip that gives some extra information about the button. I would like the tooltip to appear when the mouse hovers over the button, and then disappear when the button is clicked. Clicking the button loads a separate view.
Currently I have it so the tooltip appears on hover, but then the problem is that the tooltip sticks around after the button has been clicked. Since the button is no longer part of the current view, the tooltip jumps to the top corner of the screen for a few seconds before disappearing. I'd like it to disappear the moment the button is clicked.
So far I've tried two things to solve the problem, neither of which have worked:
I tried wrapping the JS function which opens a new view in $timeout, hoping that the tooltip would disappear before the new view loads.
I tried changing the tooltip-trigger to 'click', but now the tooltip won't appear when the mouse is hovering over it. It will appear once the button is clicked, and stay there until the view is re-loaded.
Here is my code, which includes the two failed attempts mentioned above:
Test.html:
<a class="the-button" ng-click="loadNewView($event)"
uib-tooltip-html="getToolTipInfo($event)"
tooltip-trigger="'click'"
>
Click Me!
</a>
Test.js:
ctrl.loadNewView = function($event) {
$timeout(function($event) { //timeout
SystemViews.openNewView(ctrl.newView);
});
};
Is it possible to have separate triggers for a tooltip like this? If not, what is another way that I can make sure the tooltip disappears before the new view is loaded?
Thank you very much in advance for any wisdom you'd be willing to impart.
The simplest solution is to hide the tooltip before changing view.
If your tooltip is triggered by a click on your anchor, you can emulate a click in your loadNewFunction function to hide it.
Test.html:
<a id="the-button" ng-click="loadNewView($event)" uib-tooltip-html="getToolTipInfo($event)" tooltip-trigger="'click'">Click Me!</a>
Test.js
ctrl.loadNewView = function($event) {
angular.element('#the-button').trigger('click');
SystemViews.openNewView(ctrl.newView);
};
Maybe this answer can interest you since it's about a very similar question.
I found the solution (for me, at least). I learned that you can have multiple triggers if you separate them by space. For my solution, I used the value:
tooltip-trigger='mouseenter click'.
That way it always turns on when I mouse-over, and turns off when I click.
Test.html:
<a class="the-button" ng-click="loadNewView($event)"
uib-tooltip-html="getToolTipInfo()"
tooltip-trigger="'mouseenter click'
>
Click Me!
</a>
Test.js:
ctrl.loadNewView = function() {
SystemViews.openNewView(ctrl.newView);
};
Hope someone else finds this helpful!

How to dynamically create a menu bar based on JSON using Angular Material?

I am trying to create a menu bar recursively using Angular Material Menu Bar directive, but the result is not being as expected. The best solution I have so far is to create a directive and call it recursively, like shown here: https://plnkr.co/edit/5pFmmD6K3qz5qolRifVA. Notice that there are two menu bars in this Plunker. The first is created with my recursive structure from a JSON and the second is written directly on the template. The problem with my solution happens when there are nested menus like "Lorem -> Dolor -> ...", as the nested menus are not being aligned correctly.
Inspecting the generated code on Chrome, I notice that the nested menu in the second menu bar (written directly on template) has some properties regarding its nest state:
<md-menu md-position-mode="cascade"
class="md-nested-menu md-menu ng-scope"
md-nest-level="1">
...
</md-menu>
while the same menu in the first menu bar doesn't:
<md-menu ng-if="ctrl.isCompoundedMenuItem()" class="md-menu ng-scope">
...
</md-menu>
What can I do to fix this?
Just adding an information: I have already tried an approach using ng-include to create the menu bar, but the result was terribly worse.
I was able to solve the problems with the menu behaviour by setting the attributes and classes mentioned in the question "manually" in the directive template, like this:
<md-menu ng-if="ctrl.isCompoundedMenuItem()"
md-position-mode="cascade"
class="md-nested-menu"
md-nest-level="{{ ::nestLevel }}">
Where nestLevel is in the isolated scope and is incremented on every new level:
<md-menu-content class="md-menu-bar-menu md-dense">
<my-menu-item ng-repeat="item in menu.items" menu="item"
nest-level="{{ ::(nestLevel + 1) }}"></my-menu-item>
</md-menu-content>
Starting by 1, naturally:
<md-menu-bar ...>
...
<md-menu-content>
<my-menu-item ng-repeat="item in menu.items" menu="item"
nest-level="1"></my-menu-item>
</md-menu-content>
</md-menu-bar>
The updated plunker can be seen here: https://plnkr.co/edit/QBjeR2hZFKsJ88Hl4ptG.
Sometimes we want to specify alignment on the right side of an element, for example if we have a menu on the right side a toolbar, we want to right align our menu content.
We can specify the origin by using the md-position-mode attribute on both the x and y axis. Right now only the x-axis has more than one option. You may specify the default mode of target target or target-right target to specify a right-oriented alignment target. See the position section of the demos for more examples.
<md-menu ng-if="ctrl.isCompoundedMenuItem()" md-position-mode="target-right target">
OR
It is sometimes unavoidable to need to have a deeper level of control for the positioning of a menu to ensure perfect alignment. md-menu provides the md-offset attribute to allow pixel level specificty of adjusting the exact positioning.
This offset is provided in the format of x y or n where n will be used in both the x and y axis.
For example, to move a menu by 2px from the top, we can use:
<md-menu ng-if="ctrl.isCompoundedMenuItem()" md-offset="120 0">
mdMenu API Documentation

Use an animated icon in Ionic tab

I am building an app using Ionic and am utilising the directive <ion-tabs></ion-tabs>
Each tab directive is as standard, eg:
<ion-tab title="Sync" icon-off="ion-android-sync" icon-on="ion-android-sync" href="#/tab/sync"><ion-nav-view name="tab-sync"></ion-nav-view></ion-tab>
When the app is busy syncing I'd like that static "ion-android-sync" to animate.
I see there is <ion-spinner></ion-spinner> to show spinners but I'm not sure of how to show an animated spinner icon inside a tab - anyone know how to do this?
I do not have a definitive solution for you and I am not sure whether this is the best way to do this, but in my opinion the best way to achieve this would be to dissect the <ion-tab> element, which would result in the following:
<a class="tab-item" href="#/tab/sync">
<i class="icon"><ion-spinner></ion-spinner></i>
</a>
Unfortunately, I couldn't find a spinner that looks like the ion-android-sync icon you used. And of course, more code would be necessary to make this switch between icons, but it is a start.

Use angular material to make a popup

I have the following code that opens up a pop up and displays information returned by the function //showDetails(Data.path)// when we click on the icon.
<a ng-show="Data.path" ng-click="showDetails(Data.path)">
<ng-md-icon icon="info" style="fill: green" size="15"></ng-md-icon>
</a>
I want the data to appear in a md-dialog modal window. Is there an easy way to do that ?
You have to setup a controller which tells $mdDialog what it needs to do when the showDetails(...) function is triggered.
See: https://material.angularjs.org/latest/demo/dialog (Click "View Source" <> icon, and then switch to the "JS" tab to see an example of controller code to use; or just go straight to the Codepen).
If you are using ng-include for your modal, remember Angular creates a new child scope for it. You can acess the data in the modal using the following in your modal HTML:
{{$parent.Data.path}}

How do I stop Angular-ui router from processing href

I have been supplied a bunch of html that I need to integrate with data supplied from my web api. I'm using Angular and page navigation is being handled with the Angular-ui router.
My problem is that the code I have to work with contains lots of anchors like this
<heading class="pageheader">
Scroll Down
... bunch of stuff
</heading>
<div id="step1">
... more stuff
</div>
my problem is that instead of triggering the javascript that scrolls the page down to the data entry stuff in the step1 div, a click on the link refreshes the page so I end up back at the home page view.
So I worked out that if do this
<heading class="pageheader">
<a ui-sref="state" href="#step1" class="link-scroll">Scroll Down</a>
... bunch of stuff
</heading>
I stay in my current view, but the javascript that should get triggered to scroll the page down to step1 never gets called.... any ideas for an easy way to do this?
I can work round it by changing the anchor to a div and handling the click in my angular controller, but there are lots of these in the html I have to work with.
It appears that there is some support for anchorScrolling in ui-router.
According to the aforementioned link:
A small service that handles the scrolling behind the scenes for the
autoscroll attribute directive. You can also use it if you'd like.
When called with a jqLite element, it scrolls the element into view
(after a $timeout so the DOM has time to refresh). If you prefer to
rely on anchorScroll to scroll the view to the anchor, this can be
enabled by calling $uiViewScrollProvider.useAnchorScroll().
According to this link also, autoscroll is an option as well. (Exmples from docs).
<!-- If autoscroll unspecified, then scroll ui-view into view
(Note: this default behavior is under review and may be reversed) -->
<ui-view/>
<!-- If autoscroll present with no expression,
then scroll ui-view into view -->
<ui-view autoscroll/>
<!-- If autoscroll present with valid expression,
then scroll ui-view into view if expression evaluates to true -->
<ui-view autoscroll='true'/>
<ui-view autoscroll='false'/>
<ui-view autoscroll='scopeVariable'/>

Resources