I'm fairly new to Angular, and I'm working on a simple flashcard website. Here's my current relevant HTML:
<div id="flashcards" class="row">
<div class="flashcard col-sm-6 col-md-4 col-lg-3"
ng-repeat="card in cards">
<div class="flashcard-inside"
ng-class="{'flipped' : card.flipped}">
<div class="flashcard-btns">
<button ng-click="flip(card)" class="btn btn-secondary">
<i class="fas fa-sync-alt"></i>
</button>
<button ng-click="remove(card)" class="btn btn-danger">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="flashcard-front">
<textarea ng-model="card.front"
class="form-control
flashcard-content"
ng-tabindex="{-1 : card.flipped}">
</textarea>
</div>
<div class="flashcard-back">
<textarea ng-model="card.back"
class="form-control flashcard-content"
tabindex="card.flipped ? 0 : -1">
</textarea>
</div>
</div>
</div>
</div>
I'm making a flashcard for each card in cards.
My remove and flip functions are fairly simple:
$scope.flip = (card) =>
card.flipped = !card.flipped;
$scope.remove = (card)=>
$scope.cards = $scope.cards.filter(obj=> obj.front!=card.front || obj.back!=card.back);
As you can see above, I've tried ng-tabindex="{-1 : card.flipped}" and I've tried tabindex="card.flipped ? 0 : -1" and several other combinations with no luck. I was hoping someone more experienced in Angular could point me in the right direction. It seems my problems would be solved if I could get a hold of the DOM element from the card variable in my flip scrips, and set its tabindex attribute with jQuery, however I can't seem to access the element for the textarea (which would be nice because I'd also like to focus it later).
There is no need to use ng-attr-tabindex, it can simply be done with interpolation:
<div class="flashcard-front">
<textarea ng-model="card.front" class="form-control flashcard-content"
tabindex="{{card.flipped ? -1 : 0}}"></textarea>
</div>
<div class="flashcard-back">
<textarea ng-model="card.back" class="form-control flashcard-content"
tabindex="{{!card.flipped ? -1 : 0}}"></textarea>
</div>
The problem with the code in the question is that the interpolation needs double curly brackets ({{ }}).
The ng-attr-* syntax is only necessary in exotic situations.
For more information, see
AngularJS Developer Guide - Interpolation
AngularJS Developer Guide - ngAttr for binding to arbitrary attributes
Credit to #Phix for the suggestion to use ng-attr.
The relevant part is ng-attr-tabindex="{{card.flipped ? -1 : 0}}" and the same but with !card.flipped instead of card.flipped.
My full code is:
<div class="flashcard-front">
<textarea ng-model="card.front" class="form-control flashcard-content"
ng-attr-tabindex="{{card.flipped ? -1 : 0}}"></textarea>
</div>
<div class="flashcard-back">
<textarea ng-model="card.back" class="form-control flashcard-content"
ng-attr-tabindex="{{!card.flipped ? -1 : 0}}"></textarea>
</div>
Angular Docs
Related
I have this html template file, range-details-dialog.tpl.html
<div class="modal-header clearfix text-left">
<h5>Update Range</h5>
</div>
<div class="modal-body">
<form name="form" role="form" class="ng-pristine ng-valid" novalidate ng-submit="updateRange()">
<div class="form-group-attached">
<div class="row">
<div class="col-sm-12">
<div class="form-group form-group-default input-group p-l-10 p-r-10" ng-class="{ 'has-error' : form.$invalid }">
<p ng-show="form.rangeDaily.$error.min" class="help-block">Daily range more than £5</p>
</div>
</div>
</div>
</div>
</form>
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-4 m-t-10 sm-m-t-10">
<button type="button" class="btn btn-primary btn-block m-t-5"
ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateRange()">Update</button>
</div>
</div>
</div>
Then I want to have another file forced-range-details-dialog.tpl.html
These two files could be one file instead with dynamically populated placeholders.
These are the places were substitution would be needed:
<h5>Update Range</h5> would become <h5>Update Forced Range</h5>
<p ng-show="form.rangeDaily.$error.min" class="help-block">Daily range more than £5</p>
would become:
<p ng-show="form.forcedRangeDaily.$error.min" class="help-block">Forced Daily range more than £5</p>
ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateRange()">Update</button>
, ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateForcedRange()">Update</button>
Is there a way to avoid having two separate template files for the above? Could you please provide some examples, links, or pointers as to how that can be achieved?
Also, I see in the answers that a solution would be to add a boolean parameter inside the component and then call it twice. I am not sure how to call the component though. I have pasted my component below:
angular.module('app.investment.rangeDetails')
.component('pxForcedLimitAmount', {
templateUrl: '/assets/js/apps/range/range-details-dialog.tpl.html',
bindings: {
amount: '<',
isRequest: '<?',
requestedAt: '<?',
#Input() isForced: boolean //<<----I added this based on answers below
},
controller: [function () {
var ctrl = this;
ctrl.$onInit = function () {
ctrl.isRequest = ctrl.isRequest === true || false;
};
}],
});
Seems like only the placeholders need to change, so you can use a variable to decide what placeholder to display on the template. For example:
isForced: boolean;
ngOnInit() {
this.isForced = true; // decide how you want to toggle this
}
on the template:
<h5 *ngIf="!isForced">Update Range</h5>
<h5 *ngIf="isForced">Update Forced Range</h5>
and
<p *ngIf="!isForced" ng-show="form.rangeDaily.$error.min" class="help-block">
Daily range more than £5</p>
<p *ngIf="isForced" ng-show="form.forcedRangeDaily.$error.min" class="help-block">
Forced Daily range more than £5</p>
you can do the same for other tags as well.
From the comments, one way to "determine" the value for isForced is to introduce an input property to the component i.e.
#Input() isForced: boolean;
and invoke the component from elsewhere like:
<app-user [isForced]="true"></app-user>
You can use inputs.Write a component which takes input, and render it in html. then call this component in desired places with its selector
For events use output
See the doc https://angular.io/guide/inputs-outputs
I m developping an application in which I need to redirect the current user to a different state after a ressource creation.
Actually, I have a list of demands, and I need to show or create a quotation based on that demand.
Here's the view code :
<div class="landing-diags">
<div class="current-projects">
<div class="row project-summary" ng-repeat="demand in landingdiag.demandsList">
<div class="col-md-2 project-block first-block {{project.projectType}}">
<p class="project-strong">{{demand.user.firstname}} {{demand.user.lastname}}</p>
</div>
<div class="col-md-2 project-block">
<p class="project-strong">{{demand.creationDate | date:"dd/MM/yyyy"}}</p>
</div>
<div class="col-md-4">
</div>
<div class="col-md-2">
<div ng-if="!demand.quotation">
<button ng-click="landingdiag.createQuotation(demand)" class="btn btn-primary pull-right bar-btn">Create</button>
</div>
<div ng-if="demand.quotation">
<button ui-sref="app.state.concerned({id: demand._id})" class="btn btn-primary pull-right bar-btn">Show</button>
</div>
</div>
</div>
</div>
</div>
And here's the controller methods implied :
createQuotation (demand) {
this.DemandsService.createQuotation(demand).$promise.then((response) => {
this.redirectToQuote(demand);
});
}
redirectToQuote (demand) {
this.$state.transitionTo('app.state.concerned', {id: demand._id});
}
Problem
My problem is that I m never redirected when creating a quotation. If I console log the redirectToQuote method, I pass inside of it. So it seems that my problem is on the $state.go call.
However, when I try to redirect directly using the redirectToQuote method inside of my view on the "show" button like following :
<div ng-if="demand.quotation">
<button ng-click="landingdiag.redirectToQuote(demand)" class="btn btn-primary pull-right bar-btn">Accéder au devis</button>
</div>
I m well redirected to the concerned state
I am concerned about the this.redirectToQuote within createQuotation() which is called by then() as a callback. So the this object will definitely not be your controller.
Look at the first code snippet from todd: https://toddmotto.com/resolve-promises-in-angular-routes/
He is using bind.
You can also look at https://github.com/getify/You-Dont-Know-JS/tree/master/this%20%26%20object%20prototypes from awesome Kyle Simpson
or shorter from myself: http://blog.monkey-development.com/javascript/java/2015/12/18/javascript-this.html
kibana 4 search code looks like following
<form name="queryInput" class="fill inline-form ng-valid ng-dirty" ng-submit="filterResults()">
<div class="typeahead ng-isolate-scope" kbn-typeahead="dashboard">
<div class="input-group" ng-class="queryInput.$invalid ? 'has-error' : ''">
<input input-focus="" placeholder="Filter..." class="form-control ng-isolate-scope ng-valid ng-valid-query-input ng-dirty" ng-model="state.query" kbn-typeahead-input="" validate-query="" type="text"><i style="display: none;" class="fa fa-ban input-error"></i>
<button type="submit" class="btn btn-default" ng-disabled="queryInput.$invalid">
<span class="fa fa-search"></span>
</button>
</div>
<div ng-show="typeahead.isVisible()" ng-mouseenter="typeahead.setMouseover(true);" ng-mouseleave="typeahead.setMouseover(false);" class="typeahead-items ng-hide">
<!-- ngRepeat: item in typeahead.getItems() --><div ng-repeat="item in typeahead.getItems()" ng-class="{active: item === typeahead.active}" ng-click="typeahead.selectItem(item, $event);" ng-mouseenter="typeahead.activateItem(item);" class="typeahead-item ng-binding ng-scope">
*
</div><!-- end ngRepeat: item in typeahead.getItems() -->
</div>
</div>
</form>
I have kibana dashboard in iframe in my page.
I want to have following code out of that iframe and want it to have functionality same as above code.
<input id="logsSearch" name="logsSearch" type="text"/>
to achieve this i have tried following options.
'keypress #logsSearch' : function(e){
if (e.keyCode == 13) {
var strSearch = $("#logsSearch").val();
$("#kibana").contents().find('form[name=queryInput]').find('input').val(strSearch);
var e = jQuery.Event("keydown");
e.which = 13; // # Some key code value
$("#kibana").contents().find('form[name=queryInput]').find('input').trigger(e);
$("#kibana").contents().find('form[name=queryInput]').find('button').click();
}
}
but it doesn't work. it calls /kibana4/elasticsearch/_msearch
but it doesn't call __kibanaQueryValidator.
in other solution i tried to trigger keyup, keydown events as well. but it also doesn't work
I don't know how should I do it. Any ideas or pointers or guidance to solve this problem will be a great help.
I want to add classes based on a condition in angularJs, I am following below method and it is working fine, Is there any best practice?
<div ng-if="client.status != 2" class="list-primary">
<span class="pull-right amount">{{client.receivables|number:2}}</span>
<div class="name">{{client.name}}</div>
</div>
<div ng-if="client.status == 2" class="list-primary text-muted">
<span class="pull-right amount">{{client.receivables|number:2}}</span>
<div class="name">{{client.name}}</div>
</div>
You can use ng-class for this:
<!-- apply class 'text-muted' when client.status == 2 -->
<div class="list-primary" ng-class="{ 'text-muted': client.status == 2 }">
<span class="pull-right amount">{{client.receivables|number:2}}</span>
<div class="name">{{client.name}}</div>
</div>
In angular 1.1.5+ you can use javascript ternary operator.
<div ng-class="client.status == 2 ? 'text-muted' : 'other-class'" class="list-primary ">
<span class="pull-right amount">{{client.receivables|number:2}}</span>
<div class="name">{{client.name}}</div>
</div>
I hope this helps
Have a look at ng-class which is provided in AngularJS. Documentation here:
https://docs.angularjs.org/api/ng/directive/ngClass
i've got a big performance issue.
I'm in a ng-repeat block (and i'm using track by id to improve performances).
In this block i'm generating the following dom:
1)button1A button1B
2)button2A button2B
3)button3A button3B
4)button4A button4B
5)button5A button5B
6)button6A button6B
There are some ng-show and ng-disabled in that page, on a variable that is set by ng-click on those buttons.
Performances are very poor.
On mobile we are using ng-mobile and\or fastclick for 300ms delay removing, but it seems that it tooks a lot of time to "update variables and the dom" after clicking on a button.
How can i improve performances?
Thanks a lot!
Edit: here is some code:
<div class="row" ng-repeat="date in dateRanges track by date.value">
<div ng-show="!date.custom" class="col-xs-14 col-sm-15 date-filter no-rel">
<div class="button-container button-radio"><button data-ng-class="{'radiob disabled': getDate() != date,'radiob active': getDate() == date}" ng-click="setDate(date)"></button></div>
<div class="button-container button-text">
<button class="select-date" ng-click="setDate(date)">{{date.title}} {{date.noDetails ? '' : date.start | date:'dd/MM/yyyy'}} {{date.noDetails ? '' : '-'}} {{date.noDetails ? '' : date.end | date:'dd/MM/yyyy'}}</button>
</div>
</div>
<div ng-if="date.custom" class="col-xs-2 col-sm-1 date-filter">
<button data-ng-class="{'radiob disabled':getDate() != date,'radiob active':getDate() == date}" ng-click="setDate(date)"></button>
</div>
<div ng-if="date.custom" class="col-xs-14 col-sm-15 date-filter no-rel">
<div class="row" data-ng-class="{'has-error': hasErrorComune && criteriRicerca_DateRange.custom}">
</div>
<div class="col-md-16 mrg-t-10 text-center">
<button id="Undo" ng-click="Undo()" class="btn btn-esci mrg-r-10">Undo</button>
<button type="submit" id="dropdownMovimentiConferma" ng-click="Operation()" data-ng-disabled="criteriRicerca_DateRange.custom && (hasErrorComune || hasErrorStart || hasErrorEnd)" class="btn btn-primary">OK</button>
</div>
You're testing on real mobile (harware) or emulator?
If on real, check task manager and cpu utilization.