Show and hide different contents with angularjs ng-show / ng-hide - javascript

I am new with angularjs and struggling to make some logic for Showing and hiding different Div's using ng-show and ng-hide based on different click.
PLUNKER
View 1:
<div ng-hide="section1">
<select>
<option>Select List 1</option>
<option>Select List 2</option>
</select>
</div>
<div ng-hide="section1">
<ul>
<li ng-repeat="name in names">{{name.item}}</li>
</ul>
<button type="button" ng-click="section1=!section1">Edit</button>
</div>
Initially it shows a Dropdown, some list Item and Edit button
Clicking on Edit button Everything hides and shows View 2
View 2:
<div ng-show="section1">
<button type="button" ng-click="section2=!section2">+ Create New Item</button>
</div>
<div ng-show="section1">
<ul>
<li ng-repeat="name in names">
<input type="text" ng-model="name.item">
</li>
</ul>
<button type="button" ng-click="section1=!section1">Save</button>
</div>
On view 2 There is a button "Create New item" , List of Input fields with same value of view 1's list items and a save button.
This view 2 is basically edit mode of view 1.
Upto now works fine.
Problem: If I click "+Create new item", "View 2" Should Hide and "View 3" should Open.
View 3 Contains some blank input list and "Save button".Clicking on "save button" Hide "View 3" and again open "View 1".
View 3
<div ng-show="section2">
<ul>
<li ng-repeat="name in names">
<input type="text">
</li>
</ul>
<button type="button" ng-click="section2=!section2">Save New List</button>
</div>
I am struggling to manage 3 different view based on different button click with ng-show and Hide. It's not showing and hiding properly from clicking "+create new button".
Is this possible to make it work perfectly with ng-show & ng-hide only ?
Is there any better way to handle ?
Any help will be appreciated.

A better way to handle what you're trying to do is to have a variable that holds the index of the current section. Then, you could use something like ng-show="currentSection === 1" which I think would be a little more straight forward.
Then your click action could look more like ng-click="currentSection = 1". That will show all elements with ng-show="currentSection === 1".
Does that help any?

I have modified your plunker to fix your issue. You need to use both variable in ng-show
ng-show="section1 && !section2"
http://plnkr.co/edit/rdKIT4leGM9U7BNoE01B?p=preview
There are better ways to achieve what you are trying to achieve.
Try ng-switch for example
https://docs.angularjs.org/api/ng/directive/ngSwitch

Related

Accessible dropdown menu: <li> has multiple children

I'm working on making a dropdown menu accessible. I'm largely following this W3 example: https://www.w3.org/TR/wai-aria-practices-1.1/examples/menubar/menubar-1/menubar-1.html#
However, my menu has an unusual structure. Some of my list item's contain more than one button, which are horizontally aligned within the list item.
<ul role="menu">
<li role="none">Header</li>
<li role="none">
<button role="menuitem">Option A</button>
<button role="menuitem">Option B</button>
<button role="menuitem">Option C</button></li>
<li role="none">
<button role="menuitem">Button Foo</button>
</li>
</ul>
Is there a recommended way to make this WCAG accessible?
I'd like the user to use the LEFT/RIGHT keys to move between the buttons inside a list item.
Furthermore, currently my screenreader (NVDA) will inform the user that there are 4 items within the list (due to there being 4 elements with the role="menuitem" tag). Ideally I'd like the screenreader to let the user know that there are only 2 items in the list, and then when he is on a button with siblings (e.g. "Option A" in my example), I'd like the screenreader to announce that, besides being in the first item in the menu, it is option 1 out of 3 in the list item.
Any advice is appreciated!
IMPORTANT NOTE: The menu role and pattern is designed to be used in applications. If you want to do a menu for a simple website, you should use the navigation role
Answering now, your question...
You are describing what menuitemradio role is intended for: (note: this could also be menutitemcheckbox if different options are not exclusive)
<ul role="menu">
<li role="none" id="group_header">Header</li>
<li role="group" aria-describedby="group_header">
<button role="menuitemradio">Option A</button>
<button role="menuitemradio">Option B</button>
<button role="menuitemradio">Option C</button></li>
<li role="none">
<button role="menuitem">Button Foo</button>
</li>
</ul>
I'd like the user to use the LEFT/RIGHT keys to move between the buttons inside a list item.
You can see the requisits for keyboard interactions for menu role items on the WAI ARIA Authoring practices, which include more than just the left and right keys. So you will have to rely on important javascript development for your application.
Note: Remember, that if you are designing a website (so your menu won't be in an application role), you should use the navigation role. This would be easier and you could use any standard HTML elements like input[type='radio'] which will natively handle the left and right key:
<ul role="navigation" aria-label="Menu">
<li><div id="group_header">Header</div>
<div role="group" aria-describedby="group_header">
<label><input type="radio" name="item" /> Option A</label>
<label><input type="radio" name="item" /> Option B</label>
<label><input type="radio" name="item" /> Option C</label>
</div>
</li>
<li><button>Button Foo</button></li>
</ul>
A discussion on the "menu not for website" theme

Change button in ngFor list to text field to take value and then submit for processing

First off, I'm loving Angular 2 (v5). Taken a while to "get it" but suddenly it's all made sense and really enjoying working with it.
I have a list of products generated from a WebApi service that I load into an Observable array and display on the UI using ngFor. Very simple stuff. Each item has a button to Add to Cart. Again simple and all working great.
What I want to do is make the process a bit more fluid for a user, so when a users clicks the Add to Cart button, the button is hidden and a number input spinner is revealed with an Add button, so that the user can simply select quantity at this point, prior to submitting to the AddToCart function. Otherwise they have to add to cart, then update the quantity.
I'm having a "brain not working" moment, if I'm showing and hiding elements within a ngFor list using Angular 5 with perhaps an ngIf, how do I identify that unique element or should I just use some standard JavaScript for this and if so what's the unique identifier for the element? Obviously it won't work with a variable at component level as that affects every button in the list. Perhaps I shouldn't be considering Angular at all for manipulating the DOM in this instance.
I can take the productID from the model and append that to the ID field for the button giving it an ID of something like "btn_000142" and giving the hidden element an ID of "quantity_000142" and then when the button is clicked I use some javascript (or jQuery?) to show and hide and then pass the value with the object back into the component code. But is that the right way to handle this?
Probably a stupid question, just sometimes it's hard to break the "just throw some jQuery at it" or "in MVC I'd do that easily like this..." thinking pattern! :)
Some code below:
<div *ngFor="let prod of prodDetails$ | async" [#fadeInOut] class="col-lg-3 col-md-4 col-sm-6 portfolio-item">
<div class="card h-100">
<a routerLink="{{prod.productWebFriendlyName}}"><img class="card-img-top" [src]="prod.productImgUrl" alt=""></a>
<div class="card-body">
<h4 class="card-title">
<a routerLink="{{prod.productWebFriendlyName}}">{{ prod.productName }}</a>
</h4>
<p class="card-text">{{ prod.productDescription }}</p>
<p class="card-text">{{ prod.productPrice | currency:'GBP' }}
<!-- click this button to display the div below and hide this button-->
<button type="button" (click)="addToCart(prod)" class="btn btn-primary float-right small">Add to Cart</button>
<!-- This is hidden until the Add to Cart is clicked -->
<div id="numberSpinnnerHere" style="display:none">NUMBER SPINNER HERE <button id="FinalAddToCartWithQuantity(prod, quantity)">Add</button></div></p>
</div>
</div>
</div>
You can do it in this way (trimmed the code for clearity)
<div *ngFor="let prod of prodDetails$ | async; let i = index" [#fadeInOut]>
<div class="card h-100">
<a routerLink="{{prod.productWebFriendlyName}}"></a>
<div class="card-body">
<!-- click this button to display the div below and hide this button-->
<button *ngIf="!productAdded[i]" type="button" (click)="addToCart(prod, i)" class="btn btn-primary float-right small">Add to Cart</button>
<!-- This is hidden until the Add to Cart is clicked -->
<div *ngIf="productAdded[i]" id="numberSpinnnerHere" style="display:none">NUMBER SPINNER HERE <button id="FinalAddToCartWithQuantity(prod, quantity)">Add</button></div></p>
</div>
</div>
</div>
Then in your component
productAdded = new Array(prodDetails.length)
addToCart(prod, index) {
productAdded[index] = true
}
how do I identify that unique element
It's done for you in the ngFor.
*ngFor="let prod of prodDetails
prod is the object being iterated over in the list and is the only one in the scope when referring to prod.
So use some function like isProdInCart(prod) to determine whether to show the buttons.
Although saying this, if you made a ProductCardComponent you'd avoid most of the hassle of having to do that as your component could just have a flag or something that's set when the add to cart button is clicked.

Fixed buttons for accordion's content

Scenario:
I have an accordion.
When it expands I have a form. Sometimes a long form (bigger than page height).
The form action buttons are on the end of the form.
Problem:
You must scroll the page to see/click on the action button. For some particular reason, the user may want to save it even without see all the form.
Question:
How to fix the action button in the end of the screen?
How to keep these buttons inside the accordion item (if you scroll to the end of the page, you should see other accordion item siblings)
In other words: the action buttons should be attached to the end of the screen only while the end of that accordion item is not visible yet;
Edit
Demo: http://jsfiddle.net/1vkcmo7a/1/
<div>
<accordion close-others="true">
<accordion-group heading="Item #{{i}}" ng-repeat="i in [1,2,3,4,5]">
<ul>
<li ng-repeat="a in [1,2,3,4,5,6,7,8,9,10]">long form</li>
</ul>
<button class="btn btn-success">Save</button>
</accordion-group>
</accordion>
</div>
How about enclosing the accordion item contents in a div with fixed height and a scroll e.g. <div style="max-height:50px;height:50px; overflow:auto"> ?
See http://jsfiddle.net/1vkcmo7a/7/

Put a box outside the scrollable-menu

I have a dropdown menu scrollable with options. I also have on top of that a search-box (example "CAR"). Now the search-box makes part of the scrollable menu, so when you scroll down the search box goes away. I need the search box to stay fixed on top of the scrollable menu. So basically I have to move the search box "out" of the scrollable-menu section. The problem is in my javascript code (my html is fine, thats for sure) but I cannot find it, is it possible to achieve my goal?
My BOOTPLY... [BOOTPLY][1]
Simply change your HTML like this:
<div class="dropdown-menu brand">
<div style="position: relative;">
<input class="Car" placeholder="Car" type="text">
<div class=" scrollable-menu" style="margin-bottom: 70px;">
<div class="checkbox">
<label><input value="" type="checkbox"> Alpha</label>
</div>
I moved <input class="Car" placeholder="Car" type="text"> above your scrollable-menu div, it was your HTML after all.
You should also change the variable targetinput like this:
var targetinput = currentgroup.find('.Car > input[type="text"]');
It should select your textbox propperly now, this is because you tried to find a textbox within the class scrolllable menu, however we moved the textbox outside of it.

How to make an element stop triggering ngAnimate?

I'm making a content slider for my project but I have very little expirience in AngularJS.
I've found this plunker which suits my needs greatly. You can see my live page here. It is in russian language, but I hope it wont be a problem. Slider is in the middle of the page - a section with 8 cards.
So the problem is:
Slider is controlled by the arrows below it. Still if you click on the red button inside the card it will update the model and classes ng-enter and ng-leave will be applied to the parent container which will result in slider animation. Well, the problem becomes obvious if you just click these red buttons.
Is there any way to make these red buttons not apply ng-enter and ng-leave classes to the container div?
UPDATE: Here is a plunker, that illustrates my problem. The animation must happen when you click on Prev and Next buttons. But it happens when you click on "Choose" or "Choosen" links, which updates the model.
This is a markup
<body ng-controller="MainCtrl">
<div class="page-container">
<div class="gift-page" ng-class="direction" ng-repeat="page in gifts | partition: 6 | offset: currentPage | limitTo: 1">
<ul class="gift-list clearfix">
<li class="gift" ng-repeat="gift in page">
<div class="gift-item">
<div class="gift-details">
<h3>{{gift.title}}</h3>
<span class="points">{{gift.points}} points</span>
Choose
Chosen
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="controls">
<button ng-click="prev()">Prev</button>
<button ng-click="next()">Next</button>
</div>
</body>
Quick, but not the best solution is to turn off animation before action and turn on after:
$scope.addToBasket = function(gift){
$animate.enabled(false);
gift.ordered = true;
$timeout(function(){
$animate.enabled(true);
})
}
Here is plunk.
Will look for better solution later))
Can try adding $event.stopPropagation(); to the ng-click event, in your case:
Выбрать

Categories

Resources