Can ng-model update another ng-model? - angularjs

This is my code:
<table ng-init="liveTotal={}">
<tr ng-repeat="x in sovCtrl.topics" >
<td> {{x}}</td>
<td><input ng-model="sovCtrl.objects[x]" type="number"></td>
<td ng-hide="true">
<input ng-model="liveTotal[$index]" type="number" value="{{sovCtrl.objects[x]}}">
</td>
</tr>
</table>
<div > Current Result:
{{ 0 + liveTotal[0] + liveTotal[1] + liveTotal[2] + liveTotal[3] + liveTotal[4]}}
</div>
What I'm trying to do is have a live result of the sum of all the Inputted topic values(there will never be more than 5) without using $scope or any extra sovCtrl methods/objects or adding a script;
The topics are strings I can't predict.
The 2nd input CHANGES when I type into the first input, but the result in the div does not.
The result in the div changes only when I type or press on the 2nd input(if I make it visible)
Can this be done using angular but modifying only the above HTML?
Edit: sovCtrl.objects gets passed into functions that graph the values. Modifying the the keys would break those functions.

Why don't you directly do something like shown below
wherein you directly use the first input
You just add an index (which is provided in ng-repeat of any variable) and now you can access values by using index 0,1,2,3,4
<table ng-init="liveTotal={}">
<tr ng-repeat="(i,x) in sovCtrl.topics" >
<td> {{x}}</td>
<td><input ng-model="sovCtrl.objects[x]" ng-change="sovCtrl.objects_yo[i]=sovCtrl.objects[x]" type="number"></td>
</tr>
</table>
<div> Current Result:
{{ 0 + sovCtrl.objects_yo[0] + sovCtrl.objects_yo[1] + sovCtrl.objects_yo[2] + sovCtrl.objects_yo[3] + sovCtrl.objects_yo[4]}}
</div>

Got it, this works.
<table ng-init="liveTotal={}">
<tr ng-repeat="x in sovCtrl.topics" >
<td> {{x}}</td>
<td><input ng-model="sovCtrl.objects[x]" type="number"></td>
<td ng-show="false"> {{ liveTotal[$index]= sovCtrl.shareOfVoice[x]}}</td>
</tr>
</table>
<div > Current Result:
{{ 0 + liveTotal[0] + liveTotal[1] + liveTotal[2] + liveTotal[3] + liveTotal[4]}}
</div>

Related

ng-class mix string with angular annotation

If I use this code
<td ng-class="'log-level-' + {{log.level | uppercase}}">
This is the rendered result:
<td ng-class="'log-level-' + WARN" class="log-level-">
If I remove the double brackets
<td ng-class="'log-level-' + log.level">
The rendered result is
<td ng-class="'log-level-' + log.level" class="log-level-Warn">
Is it not possible to uppercase the second log.level property in HTML and mix it with a string?
//EDIT//
NEVER MIND. Typing out the question made me realize I could use wrap the angularjs expression in a string.
<td ng-class="'log-level-' + '{{log.level | uppercase}}'">
I thought this would just render the {{log.level | uppercase}} value as a string but it still processes the expression first.
Typing out the question made me realize I could use wrap the angularjs expression in a string.
<td ng-class="'log-level-' + '{{log.level | uppercase}}'">
I thought this would just render the {{log.level | uppercase}} value as a string but it still processes the expression first.
<td class="static-class {{log.level}}">
Test
</td>
I added sample app also check Fiddler
<div ng-controller="testCtrl">
{{test}}
<table>
<tr>
<td class="static-class">
Test
</td>
</tr>
<tr>
<td class="static-class {{runtimeClass}}">
Test
</td>
</tr>
</table>
<button type="button" ng-click="addRuntimeClass()">
click
</button>
</div>
var app = angular.module('testApp',[])
app.controller('testCtrl',['$scope',
function($scope){
$scope.test='Sample test app';
$scope.addRuntimeClass = function(){
$scope.runtimeClass = 'runtime-class'
}
}])
.static-class{
display:block;
color:black;
}
.runtime-class{
display:block;
color:red;
}

ng-repeat over 11k rows crashing

I'm trying to do a table (with a lot of data) with Angular, the table is already done with PHP but to add a filter is easier using Angular. PHP takes 10secs to draw the entire table of 11k rows, but Angular keeps going on and on, even Firefox tells me that a script is unasnwered. If I click continue, the message is shown again, if I click cancel the page does nothing, if I press debug it continues running but nothing is shown.
At first, I thought that drawing +11k rows in HTML with the ng-repeat was too much and that was causing the problem, so I added a limitTo (50) and also added a infinite scroll div. But it's still not showing anything and keeps on loading.
Here is some code:
<div ng-app='mainApp'>
<div ng-init='values=[".$angularString."]' ng-controller='seeTickets as tickets'>
<div infinite-scroll='tickets.loadMore()' infinite-scroll-distance='1'>
Filtro: <input type='text' ng-model='globalSearch.$'/><br><br>
<script type='text/javascript'>
var app = angular.module('mainApp', []);
app.controller('seeTickets', function(){
this.totalDisplayed = 50;
this.loadMore = function(){
this.totalDisplayed += 50;
}
});
</script>
<table>
<tr ng-repeat="value in values | filter:globalSearch | limitTo:tickets.totalDisplayed">
<td> {{value.id_ticket}} </td>
<td> {{value.ticket_date}} </td>
<td> {{value.ticket_subject}} </td>
<td> {{value.ticket_from}} </td>
<td> {{value.ticket_to}} </td>
<td> {{value.ticket_priority}} </td>
</tr>
</table>
</div>
</div>
</div>
Am I doing something wrong? Is there a way to work this out? Why it's keep on loading even if I set limitTo?
Add track by $index to ng-repeat like this:
<tr ng-repeat="value in values | filter:globalSearch | limitTo:tickets.totalDisplayed track by $index">
...
</tr>

How to pass or reference $index in the controller

In the view (html file) I have:
<tr ng-repeat="task in ctrl.model.unplannedTasks">
<td>{{::$index + 1}}</td>
</tr>
How can I reference $index + 1 value in my controller?
I have tried doing this:
<tr ng-repeat="task in ctrl.model.unplannedTasks" ng-init="myIndex = $index + 1">
<td ng-model = "myIndex">{{myIndex}}</td>
</tr>
And then reference it in the controller with myIndex, but it is undefined.
[EDIT]
$index + 1 is the row number in the table. I would like to reference a current value of the specific row in order to be able to put it in the message like:
Are you sure you want to delete row e.g. 5? (this message is generated inside the controller)
In controller if it is use as value or otherwise use as array:
angular.module('rock').controller('test',['$scope',function($scope){
$scope.myIndex=0;
$scope.unplannedTasks="you can define your object here";
}]);
In view:
<tr ng-repeat="task in unplannedTasks">
<td myIndex={{::$index + 1}}></td>
</tr>
I just had to pass it as it is $index+1 to the function in which the message is generated.
<tr ng-repeat="task in ctrl.model.unplannedTasks">
<td>{{::$index + 1}}</td>
</tr>
...
<button type="button" class="btn btn-primary btn-xs" ng-click="ctrl.openModal(task, $index + 1)" title="{{::msg.common.button.remove}}">{{::msg.common.button.remove}}</button>

Angular ng-repeat stay paged after filter

I'm using AngularJS and I have a simple table using ng-repeat and filter. When i insert anything at the search input it filters OK but it keeps paginated as it was before I filter the table. Any ideas why this is happening ?
Here's my code:
//some var initialization
$scope.pagina = {};
$scope.pagina.currentPage = 1,
$scope.pagina.numPerPage = 10,
$scope.pagina.maxSize = 5;
//return from server with data
coresFactory.getCores().then(function(response) {
$scope.tabelaCores = response.data;
$scope.filteredTodos = $scope.tabelaCores.cores.slice(0, 10);
});
//do pagination
$scope.$watch('pagina.currentPage', function() {
var begin = (($scope.pagina.currentPage - 1) * $scope.pagina.numPerPage),
end = begin + $scope.pagina.numPerPage;
$scope.filteredTodos = $scope.tabelaCores.cores.slice(begin, end);
},true);
<input ng-model="pesquisaTabela" type="search" style="width:300px;" class="form-control input-inline" placeholder="" aria-controls="sample_1"></label>
<table class="table" style="margin-bottom:5px;border:1px solid #DDDDDD" id="sample_1">
<thead>
<tr style="background-color:#F9F9F9">
<th style="width:100px; text-align:center;"> Id </th>
<th> Nome </th>
<th> Plural </th>
<th style="width:100px; text-align:center;"> Ativo </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="cor in filteredTodos | filter:pesquisaTabela" ng-click="setSelected(cor.id)" ng-class="{linhaSelected: cor.id === idCorSelecionada}">
<td style="text-align:center;"> {{cor.id}} </td>
<td style="text-transform:capitalize"> {{cor.nome}} </td>
<td style="text-transform:capitalize"> {{cor.plural}} </td>
<td style="text-align:center;">
<span ng-if="cor.status=='sim'" class="label label-sm label-success"> Sim </span>
<span ng-if="cor.status=='nao'" class="label label-sm label-danger"> Não </span>
</td>
</tr>
</tbody>
</table>
<pagination first-text="<<" last-text=">>" next-text=">" previous-text="<" ng-model="pagina.currentPage" total-items="tabelaCores.cores.length" max-size="pagina.maxSize" boundary-links="true"></pagination>
You have quite a disconnect between various parts
Pagination is working off of one array, display from another and filter from yet another because when filter kicks in it returns a new filtered array.
The way you have things structured, your filter won't work properly either.
When you slice the main data array the filter is only going to work on that part that is sliced....not the whole main array
In order for pagination to be synchronized with filtering your simplest start point would likely be do your own filtering and share the same filtered array between the pagination and the table.
There are some other built in filters that you could use also like limitTo that takes 2 arguments limit and begin. That would help you get rid of currrent slice
There are lots of available grid/table directives available.
Using one of those would be my best suggestion
There is one other way you could do this all in the view. There is a syntax for ng-repeat that creates a new filtered array on the scope and therefore gives you access to it's length
<tr ng-repeat="row in filteredData = ( data |filter:pesquisaTabela | limitTo:10:start)">
Using this you could pass filteredData array to the total-items of the pagination directive.
It also now lets you do things like:
<div> Filtered length is: {{filteredData.length}}</div>

generating a series of buttons in two rows using angular ng-repeat

I have a angular controller that defines an array of elements as follows:
$scope.tasks = [{val=1},{val=2},{val=3},{val=4},{val=5},{val=6},{val=7},{val=8},{val=9},{val=10}];
I want to generate a series of elements for this and I can do this as follows:
<div ng-repeat-"button in tasks">
<button id = {{ $index}} value='{{task.val}}'></button>
</div>
However, I want the buttons to appear in two rows - like 1-5 in first row and 6-10 in the 2nd row. I think I have to use $index for this, but now sure how to do it.
Can someone help?
You can do it like that
<div ng-repeat-"button in tasks">
<button id = {{$index}} value='{{button.val}}'></button><br ng-if="$index == 5">
</div>
It would be better to show it in a table...
Divide the array into a 2D array with required no. of cols...
var tempArry = angular.copy($scope.tasks);
var cols = 5; //in your case 5
while (tempArry.length > 0)
$scope.DisplayArray.push(tempArry.splice(0, cols));
and the html...
<table>
<tr ng-repeat="row in DisplayArray track by $index">
<td ng-repeat="col in row track by $index">
<button value='{{col.val}}'></button>
</td>
</tr>
</table>

Resources