Show text depending of property - javascript

I want to show the text online or offline, depending on the value of a property. So if the property camera.key is null there the text offline has to be shown. Otherwise, the text online has to be shown.
So I have this template:
<h3>Camera sensoren</h3>
<table>
<th>Name</th>
<th>Last update</th>
<th>Status sensor</th>
<tr *ngFor="let camera of sensorStatusCollection.cameraSensors">
<td>{{ camera.key }}</td>
<td>{{ camera.latestTimestamp }}</td>
<td *ngIf ="camera.key === null ? online : offline "></td>
</tr>
</table>
But what I have to declare in the typescript part?
Thank you

just modify your code, put it in td body
<td>{{camera.key === null ? "online" : "offline" }}</td>
for better understanding to *ngIF if you want to use it, it an angular structural directive here you can find more about it, what is it and how to use it NgIf, here is an example for you:
<td *ngIf ="camera.key === null">online</td>
<td *ngIf ="camera.key !== null">offline</td>

Related

Get values of dynamically named inputs in Angular

In my fees-list.component.html template, I have something like the following:
<div class="container">
<div class="row" *ngFor="let meta of fees">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Amount owing (AUD)</th>
<th>Fee type</th>
<th>Title</th>
<th>Amount to pay (AUD)</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let fee of meta.fee">
<td>{{ fee.balance }}</td>
<td>{{ fee.type.desc }}</td>
<td>{{ fee.title }}</td>
<td><input id="{{ fee.id }}" type="text" name="toPay" value="{{ fee.balance }}"></td>
</tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col-md-4"><strong>Total to pay: </strong><input type="text" name="total" value="{{ meta.total_sum }}"> </div>
</div>
</div>
</div>
The requirement for my interface is twofold. If users change the value of an individual fee (fee.balance), the value in the total text input field should be updated.
Secondly, if the total input field is updated, I need to update the value(s) in the individual fees accordingly (reducing those by the appropriate amount from oldest fee to newest fee).
My question is, how do I do binding for these input fields which are dynamically generated, though they do have unique ids (id="{{ fee.id }})? I cannot work out how to target an individual fee field in my typescript file.
Use two way binding with ngModel
<input [name]="fee.id" type="text" [(ngModel)]="fee.balance">
Now when the user types in the textbox it will update the value in the array directly.
Also you should not be using {{}} binding on your attributes like that, use attribute binding with the [box] syntax.
<input type="text" name="total" [value]="total_sum">
You can calculate the total in your TypeScript like
get total_sum() {
return meta.fees.reduce((total, fee) => total + fee.balance, 0);
}
One approach ( preferred) is to create the controls dynamically.
your typescript file :
constructor(){
this.formGroup = new FormGroup();
const controls = meta.fee.map((fee)=>{
this.formGroup.addControl(fee.id, new FormControl(fee.balance))
});
// now you have a formGroup with all the controls and their value are initialized, you just need to use it in your template
}
your template :
<tbody>
<tr *ngFor="let fee of meta.fee">
<td>{{ fee.balance }}</td>
<td>{{ fee.type.desc }}</td>
<td>{{ fee.title }}</td>
<td><input id="{{ fee.id }}" [formControl]="formGroup.get(fee.id)" type="text" name="toPay"></td>
</tr>
</tbody>
So obviously, after this, you have the full power to do anything, for example, if you want to update a specific one of them:
updateValue(){
this.formGroup.get('oneOfThoseFeeIds').setValue('new value')
}
NOTE :
I haven't done Angular for a while and don't remember the exact syntaxes, but I hope this gives you a path
Can't you just use a service for that? I guess this is a way to go here, since you should try keeping your components as small as possible and communicate them by services.
Please, have a look at this chapter in angular documentation: https://angular.io/tutorial/toh-pt4

Pass a filter with a form in AngularJS?

I'm trying to teach myself AngularJS, and I've been staring at this piece of code for so long, my eyes are starting to cross.
I have a JSON file of cats containing the properties name, sex, color, pattern, and picture for each cat object. (sex in this case is a Boolean; 0 for female and 1 for male. This will come back up soon.)
I use the following code to loop through the JSON file and print out a table of all cat objects, and it works correctly (and even pretties up the formatting a bit):
<table>
<tr>
<th>Name</th>
<th>Sex</th>
<th>Color</th>
<th>Pattern</th>
<th>Picture</th>
</tr>
<tr ng-repeat="kitty in cats">
<td>{{kitty.name|capitalize}}</td>
<td ng-if="kitty.sex == 0">Female</td>
<td ng-if="kitty.sex == 1">Male</td>
<td>{{kitty.color|capitalize}}</td>
<td>{{kitty.pattern|capitalize}}</td>
<td ng-if="kitty.picture"><img ng-src="{{kitty.picture}}" alt="{{kitty.name|capitalize}}"></td>
<td ng-if="!kitty.picture">NO IMAGE</td>
</tr>
</table>
What I would like now is to allow a user to click a checkbox, e.g. "Male", and have the view change to display all cat objects where sex is 1. I can achieve this by replacing:
<tr ng-repeat="kitty in cats">
...with...
<tr ng-repeat="kitty in cats | filter:{'sex': 1}">
...but for obvious reasons, I would much prefer to have this functionality available dynamically, rather than hard-coded.
I've tried various ng-models as well as names, ids, and values on a given checkbox, but I have yet to figure out the correct syntax with which to pass the argument 1 to the repeat function, to have it filter the cats as necessary.
Does anyone have any ideas on how these two should be bound?
you probably want this:
HTML
<table>
<tr>
<th>Name</th>
<th>Sex</th>
<th>Color</th>
<th>Pattern</th>
<th>Picture</th>
</tr>
<tr ng-repeat="kitty in cats | filter : {sex: genderFilter}">
<td>{{ kitty.name }}</td>
<td>{{ kitty.sex ? 'Male' : 'Female' }}</td>
<td>{{ kitty.color }}</td>
<td>{{ kitty.pattern }}</td>
<td ng-if="kitty.picture">
<img ng-src="{{kitty.picture}}" alt="{{kitty.name|capitalize}}">
</td>
<td ng-if="!kitty.picture">NO IMAGE</td>
</tr>
</table>
<label>
<input type="checkbox"
ng-true-value="1"
ng-false-value
ng-model="genderFilter">Male
</label><br>
<label>
<input type="checkbox"
ng-true-value="0"
ng-false-value
ng-model="genderFilter">Female
</label>
PLUNKER: http://plnkr.co/edit/av2cyzJmwxJLkqhSFnOv?p=preview
You can send filter value dynamically based on selected checkbox value.
<table ng-repeat="cat in cats | filter : { sex: selectedGender }" style="width:300px">
verify this sample http://fiddle.jshell.net/w9darn8a/2/

xeditable onbeforesave not firing

I'm having issues with the xeditable directive. The onbeforesave is not firing, even though the in-place editing works fine on the client side. I can't get any reaction out of either onbeforesave or onaftersave.
I've included angular version 1.5.0 in my project.
I'm setting up the element like this, it's in a table:
<tr ng-repeat="job in jobs">
<td>{{ job._id }}<i ng-click="removeJob(job._id)" class="fa fa-trash-o" aria-hidden="true"></i></td>
<td>{{ job.title }}</td>
<td editable-text="job.description" onbeforesave="alert('hello');">{{ job.description || "empty" }}</td>
</tr>
But I haven't been able to make the alert go off when clicking save.
If you look at the documentation:
One way to submit data on server is to define onbeforesave attribute pointing to some method of scope
The onbeforesave is taking in a scope method, so alert('hello') in this case is trying to call some $scope.alert method that doesn't exist. To make this work try something like
// in your controller
$scope.test = function(data) {
alert(data);
};
// in your template
<tr ng-repeat="job in jobs">
<td>{{ job._id }}<i ng-click="removeJob(job._id)" class="fa fa-trash-o" aria-hidden="true"></i></td>
<td>{{ job.title }}</td>
<td editable-text="job.description" onbeforesave="test($data)">{{ job.description || "empty" }}</td>
</tr>
You have to give e-form as shown below (I just extracted the wrong code snippet only).
Html
<td editable-text="job.description" e-form="tableform"
onbeforesave="checkJob(job)">{{ job.description || "empty" }}</td>
JS
$scope.checkJob= function(data) {
//your logic
};

AngularJS ng-click change color within ng-repeat

I have some code that lists out items in a table from a database. The click function toggles the cells between green and red
<div class="row">
<div class="logs-table col-xs-12">
<table class="table table-bordered table-hover" style="width:100%">
<tr>
<th>Name</th>
<th>Seed</th>
<th>Division</th>
</tr>
<tr ng-repeat="team in Pool">
<td ng-class="{'btn-danger': started, 'btn-success': !started}" ng-click="inc()">{{ team.chrTeamName }}</td>
<td>{{ team.intSeed }}</td>
<td>{{ team.chrDivision }}</td>
</tr>
</table>
</div>
</div>
My click function is below
$scope.inc = function () { $scope.started = !$scope.started }
The only problem is that this is changing all of the cells in the first column. I'm thinking i need to pass a parameter in my click function, but I'm not sure what.
If you don't use the started value in your controller, you don't really need to define a function.
You could use ng-init to initialize an array keeping track of the started value for each team.
Something like this:
<tr ng-repeat="team in Pool" ng-init="started = []">
<td ng-class="{'btn-danger': started[$index], 'btn-success': !started[$index]}" ng-click="started[$index] = !started[$index]">{{ team.chrTeamName }}</td>
<td>{{ team.intSeed }}</td>
<td>{{ team.chrDivision }}</td>
</tr>
Somehow cleaner would be if there was a started property on every team instance:
<tr ng-repeat="team in Pool">
<td ng-class="{'btn-danger': team.started, 'btn-success': !team.started}" ng-click="team.started = !team.started">{{ team.chrTeamName }}</td>
<td>{{ team.intSeed }}</td>
<td>{{ team.chrDivision }}</td>
</tr>
Yes, passing a parameter into your function will help. Currently you have a $scope level variable ($scope.started) which selects your css ng-class. You probably want a team-by-team property. To do this, you should refer to the actual team object from within your ng-repeat.
<tr ng-repeat="team in Pool">
<td ng-class="{'btn-danger': started, 'btn-success': !team.started}" ng-click="inc(team)">{{ team.chrTeamName }}</td>
<td>{{ team.intSeed }}</td>
<td>{{ team.chrDivision }}</td>
</tr>
And in your javascript:
$scope.inc = function (team) { team.started = !team.started; }
Now that your are using the actual individual object (team) from your ng-repeat, everything should work fine.

How to access and use index of each item inside ng-repeat

I have a table where the last column in each row contains a little loading icon which I would like to display when a button inside the table is clicked.
When each table row is generated with ng-repeat, the loader shows up in every row rather than the individual one. How can I set ng-show to true or false for only the current index clicked?
Template:
<tr ng-repeat="record in records">
<td>{{ record.name }}</td>
<td><a ng-click="someAction(record.name)">Some Action</a></td>
<td ng-show="loading">Loading...</td>
</tr>
Controller:
$scope.someAction = function(recordName) {
$scope.loading = true;
};
You can pass in the $index parameter and set/use the corresponding index. $index is automatically available in the scope of an ng-repeat.
<td><a ng-click="someAction(record.name, $index)">Some Action</a></td>
<td ng-show="loading[$index]">Loading...</td>
$scope.someAction = function(recordName, $index) {
$scope.loading[$index] = true;
};
Here's a generic sample with all the logic in the view for convenience: Live demo (click).
<div ng-repeat="foo in ['a','b','c']" ng-init="loading=[]">
<p ng-click="loading[$index]=true">Click me! Item Value: {{foo}}<p>
<p ng-show="loading[$index]">Item {{$index}} loading...</p>
</div>
There are many ways to handle this.
The problem here is that your variable loading is sharing the scope between the rows.
One approach could be use $index
HTML
<tr ng-repeat="record in records">
<td>{{ record.name }}</td>
<td><a ng-click="someAction(record.name, $index)">Some Action</a></td>
<td ng-show="loading">Loading...</td>
</tr>
JS
$scope.someAction = function(recordName, $index) {
$scope.loading[$index] = true;
};
Using a property in your object record:
HTML
<tr ng-repeat="record in records">
<td>{{ record.name }}</td>
<td><a ng-click="someAction(record)">Some Action</a></td>
<td ng-show="record.loading">Loading...</td>
</tr>
JS
$scope.someAction = function(record) {
var name = record.name;
record.loading = true;
};
Best regards
The scope inside ng-repeat is different form the one outside. Actually the scope outside ng-repeat is the parent of the one inside. So the html code goes here
<tr ng-repeat="record in records">
<td>{{ record.name }}</td>
<td><a ng-click="someAction(record)">Some Action</a></td>
<td ng-show="$parent.loading">Loading...</td>
</tr>

Categories

Resources