I am stuck at this issue i have a list of menu item
<md-menu-item ng-value="menuItem.value" ng-repeat="menuItem in filtermenu.menuItems" ng-click="activeFilterCtrl.selectedfilter(menuItem)" translate>
<md-button>
{{ menuItem.name }}
</md-button>
</md-menu-item>
Following is the code i want to display the value of selected menu item on a button or on a label which should be displayed after selection of menu item.
Please help me resolve the issue
In your code you call the selectedFilter(menuItem) function. You can then add this in your function:
$scope.selectedFilter = function(menuItem){
// your code here
$scope.myLabel = menuItem.name;
}
And in your HTML:
<md-button>
{{myLabel}}
</md-button>
Probably the md-button directive creates its own scope and therefore menuItem is not present at this scope. Try $parent.menuItem to access the parent scope which should be the scope of ng-repeat.
Related
I am using Angular 8 with Angular Materials to build a multi-level menu. I can get the menu to work by using recursion for each level. I recursively call the same directive that displays each level of the menu.
This all works, and the menu is built as expected. However, the menu does not behave as expected. Examples I have seen, when you hover over an item, the nest item is opened, and if you move off an item, its child is closed.
For example, this is a simple version I made:
https://stackblitz.com/edit/dynamic-sidenav-multi-level-menu-tvim5b?file=app/app.component.html
Problem
My issue is when I build my menu, if I click on an item, the child opens. However, I can never get the child to close unless I click off the menu altogether. It is not behaving like the above example.
Question
How can I get my example to be have like the above, and close menu items (children) when the items loses focus?
Info
I have not put my specific example in StackBlitz because I don't own the code, and it needs backend services to support the implementation.
I think my issues are because I am building the menu items recursively , and the [matMenuTriggerFor] is referencing the menu in the next recursion.
Code
sidenav-list.component.html
<mat-nav-list>
<!-- Add the Home item -->
<a mat-list-item routerLink="/home" (click)="onSidenavClose()"><mat-icon>home</mat-icon><span class="nav-caption">Home</span></a>
<!-- Recurse over the app-sidenav-item -->
<app-sidenav-item *ngFor="let item of navItems" [item]="item" [depth]="depth+1" [sidenavClose]="sidenavClose"></app-sidenav-item>
</mat-nav-list>
sidenav-item.component.html <app-sidenav-item>
<div>
<button mat-button *ngIf="depth === 1" [matMenuTriggerFor]="menu"><mat-icon>play_arrow</mat-icon>{{item.name | titlecase}}</button>
<button mat-menu-item *ngIf="depth > 1" [matMenuTriggerFor]="menu">{{item.name}}</button>
<mat-menu #menu="matMenu">
<button *ngIf="item.actions.getItems" mat-menu-item (click)="onItemSelected(item, 0)"><mat-icon>list</mat-icon>Get Items</button>
<button *ngIf="item.actions.updateItem" mat-menu-item (click)="onItemSelected(item, 1)"><mat-icon>edit</mat-icon>Update Items</button>
<button *ngIf="item.actions.addItem" mat-menu-item (click)="onItemSelected(item, 2)"><mat-icon>add</mat-icon>Add Item</button>
<app-sidenav-item *ngFor="let child of item.children" [item]="child" [depth]="depth+1" [sidenavClose]="sidenavClose"></app-sidenav-item>
</mat-menu>
</div>
Screen Print
As you can see, I am able to open more than one item on separate nodes. I cannot get the previous one to close. Also, it only responds to clicks and not mouse hover.
Ok here is the thing, You have to preprocess some data 2 way, that means in your object you have to know if it has children to enable more hierarchy level and you need to know which parent it came from to filter it to build this
and your html should look like this. Since you know you can go 3 - 4 levels you generate template for those levels and play with data when it is there.
There is also another #input for MatMenu called matMenuTriggerData with which the parent will trigger data to child.
<button mat-button [matMenuTriggerFor]="level1" [matMenuTriggerData]="getData(null, 1)">Animal index</button>
<mat-menu #level1="matMenu">
<ng-template matMenuContent let-data="data">
<ng-template ngFor let-item [ngForOf]="data">
<button mat-menu-item *ngIf="item.children" [matMenuTriggerFor]="level2"
[matMenuTriggerData]="getData(item, 2)">{{item.label}}</button>
<button mat-menu-item *ngIf="!item.children">{{item.label}}</button>
</ng-template>
</ng-template>
</mat-menu>
<mat-menu #level2="matMenu">
<ng-template matMenuContent let-data="data">
<ng-template ngFor let-item [ngForOf]="data">
<button mat-menu-item *ngIf="item.children" [matMenuTriggerFor]="level3"
[matMenuTriggerData]="getData(item, 3)">{{item.label}}</button>
<button mat-menu-item *ngIf="!item.children">{{item.label}}</button>
</ng-template>
</ng-template>
</mat-menu>
<mat-menu #level3="matMenu">
<ng-template matMenuContent let-data="data">
<button mat-menu-item *ngFor="let item of data">{{item.label}}</button>
</ng-template>
</mat-menu>
Note the last level has no more triggers.
you can write a function for your filtered data
getData(selected, requested) {
return selected ? {
data:
this['level' + requested].filter(item => item.parent === selected.value)
} : { data: this.level1 };
}
Each item will contain value, label, parent and hasChildren in different levels, you can directly hook up with api make sure the object is passed has a data attribute , see functon getData
You can checkout this solution at https://stackblitz.com/edit/angular-yfslub
Hope you can modify to your needs.
I have a md-select dropdown menu:
<md-select ng-model="selectedCategory">
<md-option ng-repeat="category in dropdown" value="{{category.ID}}">
{{category.prop}}
</md-option>
</md-select>
And i have a span like following. When i click on span with class fa, selectedCategory becomes 0 and the encapsulating span is closed (that is normal). BUT then, for some reason, selectedCategory takes again the previous value
<span ng-show="selectedCategory!=0">{{selectedCategory.prop}}
<span class="fa fa-times delete-filter" ng-click="selectedCategory=0;"></span>
</span>
Why does selectedCategory take previous value after 0? There is no other function influencing selectedCategory
ps: if i do the same in console (selectedCategory=0), it works.
ps2: if i do the same function in a function and call that from ng-click, it works clearly too.
I'm using Angularjs with Angular Material and I have an <md-menu> that's opened when an <md-button> is clicked. I render the menu with an ng-repeat that looks like this:
<md-menu-item ng-repeat="item in orderItem.searchItems">
<md-button ng-click="orderItem.searchMenuHit($event, '{{item.field}}')">
{{item.caption}}
</md-button>
</md-menu-item>
If I right click on a menu item and inspect it with the debugger, it shows ng-click as orderItem.searchMenuHit($event,'STK_NUM') which is what I expect.
As shown in the image below:
When orderItem.searchMenuHit gets called it receives '{{item.field}}' as the value of its second parameter.
I'm not sure why this is, or how to address it. Obviously when the menu it actually rendered the item is rendered with the correct ng-click code, however; it seems when an item is clicked, the item is somehow re-rendered and the angular expression, even thought it's valid, is not evaluated.
So, I'm not sure if I'm doing something silly that made this more difficult than it should be or not, but for whatever reason, I could not get item.field to be properly passed as a parameter to my controller. I ended up passing the entire item object and that works fine.
My entire <md-menu> snippet now looks like this:
<md-menu>
<md-button class="md-icon-button" ng-click="$mdOpenMenu($event)">
<i class="material-icons md-dark">search</i>
</md-button>
<md-menu-content>
<md-menu-item ng-repeat="item in orderItem.searchItems">
<!--<md-button ng-click={{orderItem.getShortCutItem(item)}}>-->
<md-button ng-click="orderItem.searchMenuHit(item)">
{{item.caption}}
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
I've got a few dynamic accordions which based on $resource like so:
$scope.categories = $resource.query() // Written as such for simplicity sake
Then in my template I've got the following:
<accordion-group ng-repeat="category in categories" is-open="$first">
<accordion-heading>
<button ng-show="IDontKnow">...</button>
...
</accordion-heading>
</accordion>
With the above, I get my first open by default which is what I want, however I'd like to display the button above only if the accordion is open. Because $first is special variable from ng-repeat I can't change it. I've tried to use isOpen like so:
<button ng-show="category.isOpen">...</button>
But that didn't work either. How can I achieve this? Please bear in mind the accordions are based on dynamic content.
Many thanks in advance.
please see here http://plnkr.co/edit/rv6esLxJuE6NLlxwhZkh?p=preview
you can use ng-init ie: ng-init="category.isOpen=$first"
HTML:
<accordion close-others="oneAtATime">
<accordion-group ng-repeat="category in categories" is-open="category.isOpen" ng-init="category.isOpen=$first">
<accordion-heading>
I can have markup, too!
<button ng-show="category.isOpen">I'm the button</button>
</accordion-heading>
This is just some content to illustrate fancy headings.
</accordion-group>
</accordion>
If I have a ng-repeat directive bind with my initial data,
<!-- list 1-->
<li ng-repeat="data in datas">{{data.name}}</li>
and I change the data by another ng-repeat and ng-model directive,
<!-- list 2-->
<li ng-repeat="data in datas">
<input type="text" ng-model="data.name">
</li>
In Angular way, any method can do list 1 ng-repeat data refresh not immediately (after I click a Save button)?
<button ng-click="save()">Save</button>
You can use a second (temporary) clone to make the changes and copy the changes over to the actual object using angular.copy.
The actual list:
<ul><li ng-repeat="item in items">
{{item.name}} (id: {{item.id}})
</li></ul>
Edit the list:
<ul><li ng-repeat="item in tempCopy">
<input type="text" ng-model="item.name" />
</li></ul>
<button ng-click="persistChanges()">Save</button>
<button ng-click="discardChanges()">Discard</button
In your controller:
/* Persist the changes */
$scope.persistChanges = function () {
angular.copy($scope.model.tempCopy, $scope.model.items);
};
/* Discard the changes */
$scope.discardChanges = function () {
angular.copy($scope.model.items, $scope.model.tempCopy);
};
See, also, this short demo.
Finally, there is a similar example on the Angular docs on angular.copy.
It seems you are creating new items within datas by extending the array by one element? If this is so, why not use a different model for the form and push the result onto the array data when the save button is clicked?
Similarly, when editing an item, clone the array element and make it the model for the resulting form, then modify the original array element when the save button is clicked.