Incrementally add date with ng-repeat - angularjs

I have a variable $scope.date in my controller. In the view, I do ng-repeat over a couple of items. Each item has a duration in minutes. How would I go about to incrementally add time for every repeat and display this?

Add a function on the controller that calculates the date including the duration. Working code snippet:
var app = angular.module('myapp', []);
app.controller('myctrl', function($scope) {
$scope.someDate = new Date();
$scope.durations = [1, 2, 5, 6, 8];
$scope.calculateIncrementalDuration = function(index) {
var sum = 0;
for (var i = 0; i <= index; i++) {
sum += $scope.durations[i];
}
return sum;
}
$scope.calculateEndDate = function(startDate, index) {
return new Date(startDate.getTime() + $scope.calculateIncrementalDuration(index) * 60000);
}
});
.delay {
margin-top: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="myctrl">
Start time: {{someDate.toUTCString()}}
<div class="delay" ng-repeat="duration in durations">Duration in minutes: {{calculateIncrementalDuration($index)}}
<div>End time: {{calculateEndDate(someDate, $index).toUTCString()}}</div>
</div>
</div>

I don't have the reputation for a comment, so please don't be angry at me, those who get angry at non-answers as answers, but I would highly recommend looking into moment.js for things like this.

Related

How to match both the arrays in Angularjs and have to display matched one?

I have user_id in two array, one is available user_id's for projects and other is selected user_id.
availableusers = ["00000000a447a9160c9d6b74", "000000005c05c11764445bdb"]
selected Users = ["000000005c05c11764445bdb"]
Now I need to match both the array and have to display matched in selected div and unmatched in availabe div.
How can I able to do this?
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.availableusers = ["00000000a447a9160c9d6b74", "000000005c05c11764445bdb"]
$scope.selectedUsers = ["000000005c05c11764445bdb"]
$scope.matchUser = [];
for (var i = 0; i < $scope.availableusers.length; i++) {
for (var j = 0; j < $scope.selectedUsers.length; j++) {
if ($scope.availableusers[i] === $scope.selectedUsers[j]) {
$scope.matchUser.push($scope.availableusers[i]);
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<span>Available users</span>
<div ng-repeat="available in availableusers">{{available}}</div>
<span>Selected Users</span>
<div ng-repeat="selectUser in selectedUsers">{{selectUser}}</div>
<span>Users</span>
<div ng-repeat="Users in matchUser">{{Users}}</div>
</div>
var result=[];
for(var i = 0 ;i<availableUsers.length;i++){
if(availableusers[i] === selectedUsers[i])
{
result.push(availableusers[i]);
}
}

Swapping data on ui-grid take a lot of time

I have one grid and according to some conditions, I have to change the data which comes from the back-end.The first time I load data from the back the grid works fine. When I start switching data the grid displays new data well but stays frozen for a while. I notice that this time is random and is often about 3 seconds or plus.
I tried to assign data to the grid through different ways but the result is the same:
1)
$scope.gridOptions = {
//some options,
data: $scope.myData
}
And then
Demande.query({lb: condition}, function (result) {
$timeout(function () {$scope.myData = result;},0);// I also try without $timeout
}
2) I try to assign the data directly to the grid
Demande.query({lb: condition}, function (result) {
$timeout(function () {$scope.gridOptions.data = result;},0);
}
3) I combine the above approachs with
a) $scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.ROW)
b) $scope.gridApi.core.refreshRows()
but the problem persists. I am using angular-ui-grid 4.0.1
Any idea will be appreciated.
Another option:
4) $scope.gridOptions.data = angular.copy($scope.myData);
Should give the grid the little time that it needs to breath!
Update:
angular.module('app', ['ui.grid'])
.controller('MainCtrl', ['$scope', function($scope) {
$scope.gridOptions = {
columnDefs: []
}
for (var i = 0; i < 80; i++) {
$scope.gridOptions.columnDefs.push({
name: 'C' + (i + 1),
enableColumnMenu: false
});
}
var dataLoadCounter = 1;
$scope.switchData = function() {
$scope.gridOptions.data = [];
for (var i = 0; i < 1000; i++) {
$scope.gridOptions.data.push({});
for (var j = 0; j < 80; j++) {
$scope.gridOptions.data[i]['C' + (j + 1)] = 'D' + dataLoadCounter + (j + 1);
}
}
dataLoadCounter++;
}
$scope.switchData();
}]);
div[ui-grid] {
width: 4500px;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.2/ui-grid.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.2/ui-grid.min.css" />
<div ng-app="app" ng-controller="MainCtrl">
<button ng-click="switchData()">Switch Data</button>
<div ui-grid="gridOptions">
</div>
</div>

rendering html from a controller in angular

Hopefully someone can point my in the right direction.
I am building a web app and part of it requires a user to click a button as fast as they can to obtain a score. The design dictates that I will need to show this score in double digits i.e 9 would be 09 so for styling I need to wrap span tags around each digit.
I have got everything working as required, I'm just having an issue with outputting the score that is wrapped in span tags as rendered html in my view.
I've put together a fiddle for the section that is causing me problems. Any advice, help, best practices etc is much appreciated.
What I've tried:
I've included a few of the things I've tried. Basically they involve using $sce and trying to ng-bind-html in the view. Attempt 3 seems the most logical to me but the $scope.count isn't being updated. I'm guessing I need to add a $watch or $apply function to keep it binded? but I'm not too sure how to implement it or even if this is good practice. Also, because I'm outputting html is it better practice to do this in a directive?
Fiddle http://jsfiddle.net/funkycamel/gvxpnvqp/4/
HTML
<section ng-app="myApp">
<div ng-controller="MyController">
<button ng-click="add(1)">add</button>
<!-- First attempt -->
<p class="first-attempt">{{ pad(count) }}</p>
<!-- Second attempt -->
<!-- in order for this attempt to work I have to call the pad2 function which
returns trustedHtml -->
{{ pad2(count) }}
<p class="second-attempt" ng-bind-html="trustedHtml"></p>
<!-- Third attempt -->
<p class="third-attempt" ng-bind-html="moreTrustedHtml"></p>
</div>
Javascript
var app = angular.module('myApp', []);
app.controller('MyController', ['$scope', '$sce', function ($scope, $sce) {
// Set initial count to 0
$scope.count = 0;
// function to add to $scope.count
$scope.add = function (amount) {
$scope.count += amount;
};
// Attempt 1
// make sure number displays as a double digit if
// under 10. convert to string to add span tags
$scope.pad = function (number) {
var input = (number < 10 ? '0' : '') + number;
var n = input.toString();
var j = n.split('');
var newText = '';
var trustedHtml = '';
for (var i = 0; i < n.length; i++) {
newText += '<span>' + n[i] + '</span>';
}
return newText;
};
// Attempt 2 - trying to sanitise output
// same as above just returning trusted html
$scope.pad2 = function (number) {
var input = (number < 10 ? '0' : '') + number;
var n = input.toString();
var j = n.split('');
var newText = '';
var trustedHtml = '';
for (var i = 0; i < n.length; i++) {
newText += '<span>' + n[i] + '</span>';
}
// return sanitised text, hopefully
$scope.trustedHtml = $sce.trustAsHtml(newText);
return $scope.trustedHtml;
};
// Attempt 3
// Trying to sanitise the count variable
$scope.moreTrustedHtml = $sce.trustAsHtml($scope.pad($scope.count));
}]);
These currently output
<span>0</span><span>0</span>
<span>0</span><span>0</span>
00
00
Again any advice/help is greatly appreciated.
Far simpler solution:
HTML
<p>{{ count < 10 ? '0' + count : count}}</p>
Controller:
app.controller('MyController', ['$scope', function ($scope) {
$scope.count = 0;
$scope.add = function (amount) {
$scope.count += amount;
};
}]);
DEMO
If you prefer you can do the padding in the controller instead, just use another variable
app.controller('MyController', ['$scope', function ($scope) {
var count = 0;
$scope.countText = '0';
$scope.add = function (amount) {
count += amount;
$scope.countText = count < 10 ? '0' + count : count;
};
}]);

ngRepeat dont refresh when I change the values - AngularJS

I'm doing a application to a calendar and I create a function that everytime change the values of my variable called "$scope.days", when I was using the version 1.0 didnt give error, but now the ngRepeat doesnt refresh, the new values go to the variable, but the ngRepeat dont show the new result...
$scope.loadMonth = function()
{
$scope.titleCalendar = $scope.months[$scope.month-1].name + ' ' + $scope.year;
getTotalFebruary($scope.year);
var dtString = $scope.year + '/' + $scope.month + '/' + 1,
date = new Date(dtString),
day = 1,
weekday = date.getDay(),
totalDays = $scope.months[date.getMonth()].qty + date.getDay();
$scope.days = [];
for(var i = 0; i < totalDays; i++)
{
if(i < weekday)
$scope.days.push('');
else
$scope.days.push(day++);
}
};
my html:
<div class="day" ng-repeat="day in days"><p>{{ day }}</p></div>
If I put an alert after push new values, I can see the new values, but my ngRepeat doesnt refresh the results, I already try many things but didnt work. Somebody know the solution?
Not sure I understand what you are trying to achieve given the small sample of code you provided but if you look at this sample you'll see that it should update the display every time you click the click me text, just enter either 1,2, or 3 in the input area. you might want to check that looping logic of yours.
<html lang="en-US" ng-app="mainModule">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min.js"></script>
</head>
<body>
<div ng-controller="mainController">
<input type="text" ng-model="monthModel" placeholder="enter 1 2 or 3"/>
<h1 ng-click="loadMonth(monthModel)">Click Me to Repeat</h1>
<span class="day" ng-repeat="day in days">{{ day }} , </span>
</div>
<script type="text/javascript">
var app = angular.module("mainModule", []);
app.controller("mainController", function ($scope) {
//$scope.monthModel = 1; // default some date
$scope.year = "2014";
$scope.months = [
{"name":"January", "qty":10},
{"name":"February", "qty":5},
{"name":"March", "qty":10},
];
$scope.loadMonth = function(monthModel)
{
$scope.month = monthModel;
$scope.titleCalendar = $scope.months[$scope.month-1].name + ' ' + $scope.year;
//getTotalFebruary($scope.year);
var dtString = $scope.year + '/' + $scope.month + '/' + 1,
date = new Date(dtString),
day = 1,
weekday = date.getDay(),
totalDays = $scope.months[date.getMonth()].qty + date.getDay();
$scope.days = [];
for(var i = 0; i < totalDays; i++)
{
//if(i < weekday)
// $scope.days.push('');
//else
$scope.days.push(day++);
console.log($scope.days) ;
}
};
});
</script>
</body>
</html>

Moving angularJS elements created by ng-repeat

I'm trying to move elements that are created by a ng-repeat into some columns. I successfully did it with a directive, but the problem happens when I sort the array of objects on which ng-repeat operates. The directive that searches for the smallest column and then insert the element in it fails to determine the smallest column (maybe because there are still elements in the columns).
I believe the structure I use (directives / controllers etc...) isn't optimal, and I cannot find how to organize the angular code to get the behavior I want.
Here is a jsFiddle showing what I have now : http://jsfiddle.net/kytXy/6/ You can see that the items are being inserted correctly inside the columns. If you click on a button that re-arranges the sorting, then they are not inserted again. If you click multiple times on a same button, watch what happens...
I put commented alerts that you can uncomment so that you can see how items are being inserted and what is wrong. I've also tried emptying the columns before inserting again (commented js in the jsfiddle), whithout any success.
Here is the code :
HTML:
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<div ng-app="myModule">
<div ng-controller="Ctrl" >
<button ng-click="predicate = 'id'; reverse=false; setupColumns()">Sort ID</button>
<button ng-click="predicate = 'id'; reverse=true; setupColumns()">Sort ID reversed</button>
<div id="columns" generate-sub-columns post-render>
</div>
<div class="elements">
Elements are stored here !
<div class="element" ng-repeat="(key,elt) in elts | orderBy:predicate:reverse" id="element{{key}}">
Text: {{elt.a}}
</div>
</div>
</div>
</div>
JS:
var myModule = angular.module('myModule', []);
myModule.controller('Ctrl', function($scope) {
$scope.predicate='id';
$scope.reverse=false;
$scope.elts = [
{id:0,a:"Hi man !"},
{id:1,a:"This is some text"},
{id:2,a:"Wanted to say hello."},
{id:3,a:"Hello World!"},
{id:4,a:"I love potatoes :)"},
{id:5,a:"Don't know what to say now. Maybe I'll just put some long text"},
{id:6,a:"Example"},
{id:7,a:"Example2"},
{id:8,a:"Example3"},
{id:9,a:"Example4"},
{id:10,a:"Example5"},
{id:11,a:"Example6"}
];
$scope.setupColumns = function() {
console.log('calling setupColumns');
var eltIndex = 0;
var element = jQuery("#element0");
/*while(element.length > 0) {
jQuery('#elements').append(element);
eltIndex++;
element = jQuery("#element"+eltIndex);
alert(1);
}
alert('Columns should be empty');*/
element = jQuery("#element0");
eltIndex = 0;
var columnCount = 0;
while (jQuery("#column"+columnCount).size() >0)
columnCount++;
while(element.length > 0) {
console.log('placing new element');
var smallestColumn = 0;
var smallestSize = jQuery("#columns").height();
for (var i = 0; i < columnCount; i++) {
var columnSize = jQuery(".column#column"+i).height();
if (columnSize < smallestSize) {
smallestColumn = i;
smallestSize = columnSize;
}
};
jQuery('.column#column'+smallestColumn).append(element);
eltIndex++;
element = jQuery("#element"+eltIndex);
//alert(1);
}
//alert('Columns should be filled');
};
});
myModule.directive('generateSubColumns', function() {
return {
restrict: 'A',
controller: function() {
var availableWidth = jQuery("#columns").width();
var sizePerColumn = 100;
var nbColumns = Math.floor(availableWidth/sizePerColumn);
if (nbColumns<=1)
nbColumns=1;
for (var i = 0; i < nbColumns; i++) {
jQuery('<div class="column" id="column'+i+'">Column '+i+'</div>').appendTo('#columns');
};
}
};
});
myModule.directive('postRender', [ '$timeout', function($timeout) {
var def = {
restrict: 'A',
terminal: true,
transclude: true,
link: function(scope, element, attrs) {
$timeout(scope.setupColumns, 0);
}
};
return def;
}]);
and some css:
#columns {
width: 100%;
}
.column {
width: 100px;
display:inline-block;
vertical-align: top;
border: 1px solid black;
}
.element {
border: 1px solid red;
}
How can I fix that ?
Thanks in advance,
hilnius
First.. Why you are doing something like this?
var element = jQuery("#element0");
Inside a controller?
That kind of code (DOM manipulation) should go inside link function directive and use the $element parameter to access to DOM element.
Also.. What if you use the column-count property to divide your container? https://developer.mozilla.org/es/docs/Web/CSS/column-count

Resources