I have a set of tabs:
<tabset class="tab-container">
<tab id = "tabContent" ng-repeat="tab in tabs" active="tab.active" ng-model = "cmModel"> <!-- the tab highlight directive -->
<tab-heading>
<span>{{tab.title}}</span>
<i class="glyphicon glyphicon-remove" ng-click="removeTab($event, $index)"></i> <!-- the tab close button -->
</tab-heading>
<textarea ui-codemirror='cmOption' id="{{ 'Tab ' + ($index+1) }}" ng-model = "Text"> + "awefwef" + </textarea>
</tab>
<button class="btn btn-default" ng-click="addTab()"></button>
</tabset>
I'm attempting to set a dynamic ng-model with ng-model = "Text".
First of all, I know that if I really want to add dynamic ng-models, I can't have them all the same (need to somehow add $index to Text). However, the most pressing issue is that $scope.Text is undefined, even though I clearly have added a textarea with ng-model Text.
What am I doing wrong?
Thanks.
I thinks if the value of your ng-model can not be find in the tabs, it will get a undefined.
Why don't you just make text a property of each tab? So instead of doing this:
<textarea ng-model="Text[tab.title]"></textarea>
Do this:
<textarea ng-model="tab.text"></textarea>
Text[Value]
That implies you're trying to access a property called "Value" on an object called "Text". If it was just "Text" then angular would create a variable called "Text" on your scope object and all would be well but since you're trying to access a property on the variable before it has actually been created you're getting the reference error.
I'm assuming you have a controller, in which case do:
$scope.Text = {}
within the controller and what you have should work.
I am assuming the issue you're running into is trying to have each tab have their own scope for the tab title. To work with your current setup, you will need to just have the model for the <textarea> be set to the tab.title itself. This way, it will be tied to that particular tab.
<tabset class="tab-container">
<tab ng-repeat="tab in tabs" ng-model="cmModel">
<tab-heading>
<p>{{tab.title}}</p>
</tab-heading>
<br/>
<textarea id="{{"Tab"+($index+1)}}" ng-model="tab.title"></textarea>
</tab>
<p><button class="btn btn-default" ng-click="addTab()">Add Tab</button></p>
</tabset>
Working JSFiddle Demonstration
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 this two buttons:
<button onclick="filterSelection('Action')">Action</button>
and
<button onclick="filterSelection('Adventure')">Adventure</button>
Now, I want to do the same but with Vue.JS, so I created this array on my app.js
genres: [{name: 'Action'}, {name:'Adventure'}]
And in my HTML file:
<button v-for="genre of genres">{{genre.name}}</button>
That's works fine, but I don't know how to add the propertie with Vue.JS:
onclick="filterSelection('genre')"
Can you help me?
You can do this by having the attribute v-on:click="filterSelection(genre)" on your button.
Edit: Forgot quotes.
Since vue uses a virtual dom, you cannot use the "native html" events.
Instead you define click events via an event handler [docs]
<div id="example-1">
<button v-on:click="counter += 1">
Add 1
</button>
<p>
The button above has been clicked {{ counter }} times.
</p>
</div>
alternatively you can use the shorthand for v-on and use the # symbol like #click=
I have this view template that is a child to another view.
The parent view of this view is a child to the index.html where I am importing my angular and ui-router javascript.
i.e index.html > other view > view below
When I try to change the class = "bubble me" below - which works fine ,to ng-class = "bubble me" my css is not loaded. Am I missing something? The issue is isolated to this view only.
<div class="top"><span>To: <span class="name">{{chat.name}}</span></span></div>
<div class="chat">
<div class="conversation-wrapper">
<div class="conversation-start">
<span>Today, 6:48 AM</span>
</div>
<div class="bubble me" ng-repeat = "message in sent_received">
{{message.msg}}
</div>
<div class="write">
<input ng-model = "input.message" type="text" />
<a ng-click= "sendMsg()" class="write-link send"></a>
</div>
does ng-class work only for conditional classes? I would like to
combine my regular hard coded classes with the conditional ones so I
dont have both a class attribute and an ng-class attribute in my
tags..is there no way of doing this? - in the code above the bubble is
not dynamic. I would like to make the me class only dynamic
This might work for your case.
ng-class="value=='true'?'bubble me':'bubble'"
I have an input box with the ng-model attribute in my ionic based application. The code inside the ion-content tag:
<ion-content class="padding">
<input ng-model="myNumber" type="number" placeholder="Enter number">
</ion-content>
And in the footer-bar I have this:
<div class="bar bar-footer bar-balanced" style="background-color: #00368C !important; color: #fff;">
<div class="title">
<button ng-click="submit(myNumber)" class="button button-clear">Submit</button>
</div>
</div>
The alert result is undefined.
NOTE: when I put the button inside the ion-content it works fine. (It means js codes works fine)
Any idea?
The reason behind your problem is, ion-content directive does create a child scope which is prototypically inherited from the parent scope. So by placing myNumber in input ng-model does get added inside the scope of ion-content, which is different that the controller myNumber number scope variable.
To make it working you need to follow dot rule while defining ng-model, so that prototypal inheritance rule will get follow(it works on reference type variable).
So create an new object inside a controller and do assign all ng-model variable into it. like below
$scope.model = {};
And then put all the properties you wanted to use on view like $scope.model.myNumber & while using it on view use it like model.myNumber
Markup
<ion-content class="padding">
<input ng-model="model.myNumber" type="number" placeholder="Enter number">
</ion-content>
<div class="bar bar-footer bar-balanced" style="background-color: #00368C !important; color: #fff;">
<div class="title">
<button ng-click="submit(model.myNumber)" class="button button-clear">Submit</button>
</div>
</div>
Detailed explanation can be found in this answer
More elegant way of doing it would be using controllerAs approach.
A better and simpler solution, use <ion-header-bar> or <ion-footer> and place all your pinned content in there - and then keep all your code in the same controller.
Referenced from: https://stackoverflow.com/a/51785866/2036221
I'm new to AngularJS and having to work on an app that has a section of nested ngRepeats such as this below.
<div class="title-bar" ng-repeat="orderType in someObj.orderTypes">
<div class="inner-panel" ng-repeat="status in orderType.statuses">
<p>{{status.Name}}</p>
<div class="order-list" ng-repeat="order in status.Orders | limitTo:orderFilterLimit">
<p>{{order.Stuff}}</p>
</div>
<button ng-show="(status.Orders.length > orderFilterLimit)" ng-click="loadMoreOrdersToList()">Load More</button>
</div>
</div>
The status.Orders list can be quite large at times so I limit it. When a user wants to view more data for that specific section (which is enumerated by status) I add 3 to the orderFilterLimit. The problem is when I do this it is adding 3 to every single .order-list in the .inner-pannel element. Is there a way I can change the orderFilerLimit variable based on an id or class of the element it's attached to?
For context here is a super simple snippet of what loadMoreOrdersToList() is doing.
https://jsbin.com/vapucixesa/1/edit?js
No need of declare the orderFilterLimit inside controller, You should have scope variable inside ng-repeat itself so that it ng-repeat element will have separate copy of orderFilterLimit because ng-repeat create a child scope on each iteration.
Markup
<div class="title-bar" ng-repeat="orderType in someObj.orderTypes" ng-init="orderFilterLimit = 3">
<div class="inner-panel" ng-repeat="status in orderType.statuses">
<p>{{status.Name}}</p>
<div class="order-list" ng-repeat="order in status.Orders | limitTo:orderFilterLimit">
<p>{{order.Stuff}}</p>
</div>
<button ng-show="(status.Orders.length > orderFilterLimit)" ng-click="orderFilterLimit = orderFilterLimit + 3">Load More</button>
</div>
</div>