Using angular to display different timestamps depending on age of object - javascript

This is similar to the messages app on an iphone, where newer text messages you get will simply show you the time in a format like 9:55 PM, but once they are a day old it says Yesterday, and anything older than a day says the day of that week Monday, Tuesday, etc, anything older than that week just displays that date like 12/22/2014.
I've been able to successfully format my timestamps using the date filter:
{{message.timestamp | date:"h:mm a" }}
What would work best for something like this, a custom filter? Is it possible purely in angular?

You can use moment.js date library with angular filter to achieve that. moment has various standard formatting expressions available. Take a look at the documentation.
Include moment.js in your application, you can download it or refer to a cdn location. Example:
//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js
Create a filter:
.constant('moment', window.moment) //Save moment in constant for ease of dependency injection
.filter('dateMoment', ['moment', function(moment){
return function(input){
//Return formatted date
if(!input) return '_';
return moment(input).calendar();
}
}]);
Use the filter with the binding:
{{message.timestamp | dateMoment }}
Demo
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, moment) {
var currDt = new Date();
$scope.messages = [{
message: 'message1',
date: currDt
}, {
message: 'message11',
date: (new Date(currDt)).setDate(currDt.getDate()-1)
}, {
message: 'message3',
date: (new Date(currDt)).setDate(currDt.getDate()-3)
}, {
message: 'message4',
date: (new Date(currDt)).setDate(currDt.getDate()-4)
}, {
message: 'message5',
date: (new Date(currDt)).setDate(currDt.getDate()-5)
}, {
message: 'message2',
date: (new Date(currDt)).setDate(currDt.getDate()-30)
}]
}).constant('moment', moment).filter('dateMoment', ['moment',
function(moment) {
return function(input) {
return moment(input).calendar();
}
}
]);
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="moment.js#*" data-semver="2.8.3" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js"></script>
<script data-require="angular.js#1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="msg in messages">{{msg.message}} ---- {{msg.date|dateMoment}}</div>
</body>
</html>

Related

Dynamic date blockouts jquery datepicker

I have a custom appointment form with multiple locations. On Sundays all locations are closed. On Saturdays only a few locations are open. One location is so busy that all appointments need to be 1 week in advance at the very least.
I was finding answers saying, "You cannot update the current picker. You need to destroy it, set the reserved dates in an array, and rebuild the datepicker with those options.", which meant duplicating the datepicker that's on the custom form with all it's odd regional formats and options.
Then, after telling everyone it's going to be more work than it's worth I found out you can just out the next 7 days dynamically with:
$('input.datepicker').datepicker( 'option', 'minDate', '+7d');
That works! Then also found you could tell the current datepicker to switch to today's date with this:
$('input.datepicker').datepicker('setDate', 'today');
So can I get a live datepicker to hide weekends? I should be able to but the option I found fails:
$('input.datepicker').datepicker({ beforeShowDay: jQuery.datepicker.noWeekends });
I really want to be able to say, "no weekends" or "no sundays", without destroying and rebuilding, but it's not a popular topic since most forms don't need to update the datepicker dynamically.
Here's a simple fiddle of what I'd like to accomplish: https://jsfiddle.net/56qsau34/
EDIT: So I was really close but I had the wrong method(?) for applying an update to the live datepicker. If you take the last guess and write it properly it works!
$('input.datepicker').datepicker( 'option', 'beforeShowDay', jQuery.datepicker.noWeekends );
EDIT #2: Just for the poor soul that finds this without the final solution. When you realize that you need to 'toggle' the noWeekends feature this function that returns all the dates with 'true' will come in real handy:
$('input.datepicker').datepicker('option', 'beforeShowDay', function(d) {
var year = d.getFullYear(),
month = ("0" + (d.getMonth() + 1)).slice(-2),
day = ("0" + (d.getDate())).slice(-2);
var formatted = year + '-' + month + '-' + day;
//is it a sunday - this was the missing bit for all my specs
if (d.getUTCDay() != 0) {
return [true, "",""];
}else{
return [false, "",""];
}
}
Yes, you can change the options without destroying the widget.
$.datepicker.noSundays = function (date) {
return [ date.getDay() != 0, "" ];
}
$("#foo").click(function() {
$("input").datepicker();
});
$("#nowknd").click(function() {
$("#datepicker").datepicker('option', 'beforeShowDay', $.datepicker.noWeekends);
});
$("#okwknd").click(function() {
$("#datepicker").datepicker('option', 'beforeShowDay', '');
});
$("#nosuns").click(function() {
$("#datepicker").datepicker('option', 'beforeShowDay', $.datepicker.noSundays);
});
$("#weekblock").click(function() {
$("#datepicker").datepicker('option', 'minDate', '+7d');
});
<link href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<p>Date:<input type="text" id="datepicker"></p>
<p>
<button id="foo">Make it a datepicker</button>
<button id="nowknd">Block weekends</button>
<button id="okwknd">Allow weekends</button>
<button id="nosuns">Block Sundays</button>
<button id="weekblock">Block off a week</button>
</p>
Does this help?
Can the jQuery UI Datepicker be made to disable Saturdays and Sundays (and holidays)?
weekends visible but not selectable.
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!--
want to hide weekends from calendar
https://stackoverflow.com/questions/501943/can-the-jquery-ui-datepicker-be-made-to-disable-saturdays-and-sundays-and-holid
-->
<title>jQuery UI Datepicker - Disable the Selection of some days </title>
<link href="jquery-ui-1.10.3.css" rel="stylesheet">
<script
src="https://code.jquery.com/jquery-2.2.0.min.js"
integrity="sha256-ihAoc6M/JPfrIiIeayPE9xjin4UWjsx2mjW/rtmxLM4="
crossorigin="anonymous"></script>
<script
src="https://code.jquery.com/ui/1.10.3/jquery-ui.min.js"
integrity="sha256-lnH4vnCtlKU2LmD0ZW1dU7ohTTKrcKP50WA9fa350cE="
crossorigin="anonymous"></script>
<script type="text/javascript">
$(function () {
$(".datepicker1").datepicker({
beforeShowDay: $.datepicker.noWeekends
});
});
</script>
</head>
<body>
<h3>Click in the TextBox to select a date :</h3>
<p>weekends are not selectable</p>
<input type="text" class="datepicker1" />
</body>
</html>

AngularJS - Add 6 hours to input date to JSON

I don't know how can I add 6 hours to input date in AngularJS.
I've try this :
var eventStart = new Date ($scope.event.startdateid);
var startDate = new Date ( eventStart );
startDate.setHours ( eventStart.getHours() + 6 );
event.startdateid = new Date(startDate).toJSON();
But nothing happen ...
This is my HTML :
<input type="date" name="startdateid" ng-model="event.startdateid" min="{{date | date:'yyyy-MM-dd'}}">
Can you tell me when I make mistake ?
Thank you !
First you don't need to convert nothing to JSON and your code seems correct (disregarding the fact that you aren't using even the $scope or controllerAsSyntax to send your variables to view -I'll prefer to think it was just to put here in question-), maybe you may have made some mistakes in his view.
So you just need to use ngChange directive to achieve this.
Here is a snippet working:
var app = angular.module('app', []);
app.controller('mainCtrl', function($scope) {
$scope.setHours = function() {
$scope.event.startdateid.setHours($scope.event.startdateid.getHours() + 6);
}
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl">
<input type="date" name="startdateid" ng-model="event.startdateid" min="{{date | date:'yyyy-MM-dd'}}" ng-change="setHours()">
<hr>
<!-- The date with +6 hours -->
<span ng-bind="event.startdateid | date:'yyyy-MM-dd HH:mm'"></span>
</body>
</html>
Why not momentJS?
moment(someDate).add(6, 'hours');
I'd recommend using Datejs
One way by doing it in JavaScript pure, no third party lib:
Date.prototype.addHours = function(h) {
this.setTime(this.getTime() + (h*60*60*1000));
return this;
}
Or just update the time for 6 more hours Like your code:
startDate.setTime(this.getTime() + (6*60*60*1000));

Angular Filter, compare JSON file date to today's date

<p id="appt_time" ng-if="x.dateTime | date: MM/dd/yyyy == {{todaysDate}}">SHOW ME IF TRUE{{todaysDate}} </p>
Plunkr:https://plnkr.co/edit/r2qtcU3vaYIq04c5TVKG?p=preview
x.dateTime | date: MM/dd/yyyy gets a date and time which turns out to be when filtered: 06/18/2016 according to my json file.
What I'm trying to accomplish is to compare this "x.dateTime" to today's date and show the paragraph if the statement is true. So in my angular file, I have a $scope.todaysDate = "06/18/2016", but the paragraph doesn't show.
HTML file:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="https://code.angularjs.org/1.5.5/angular.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="x in information">
<!--Compare Json Object to Javascript Object-->
<p ng-if ="x.dateTime">{{x.dateTime | date: MM/dd/yyyy }}</p>
<!--Compare Json Object to Today's Date-->
<p id="appt_time" ng-if="x.dateTime.valueOf() === todaysDate.valueOf()">Open in: {{todaysDate}} </p>
</div>
</body>
</html>
JS File:
// declare a module
var myAppModule = angular.module('myApp', []);
var todaysDate = new Date();
// configure the module.
// in this example we will create a greeting filter
myAppModule.controller('myCtrl', ['$scope','$http', function($scope, $http)
{
$scope.todaysDate = todaysDate;
$scope.test = "Volvo";
$http.get("time.json")
.then(function(data) {
$scope.information = data;
});
}]
);
JSOn file:
{
"dateTime":"2016-06-18T18:41:00.748-04:00"
}
Because you're dealing with dates and times, things can get tricky fast. I would suggest using the Moment.js library, as it makes this super easy:
ng-if="moment.utc(x.DateTime).isSame(todaysDate, 'day')"
The "day" there indicates how granular you want to compare the two values. However, it's relatively easy even without that library:
ng-if="x.DateTime.substring(0, 10) === todaysDate"
Where you change $scope.todaysDate to "2016-06-18".
You can add a validate function which will return true if date is today. Don't forget to inject $filter.
$scope.validate = function(date) {
return $filter('date')(date. 'your format') === $filter('date')(new Date(). 'your format');
}
In html
<p id="appt_time" ng-if="validate(x.dateTime)">SHOW ME IF TRUE{{x.dateTime}} </p>
See the foll link:
https://plnkr.co/edit/ZLJB5i1nQu9RYUV5FAX3?p=preview
// time.json
[{
"dateTime":"2016-06-18T18:41:00.748-04:00"
}]
//script.js
$http.get("time.json")
.then(function(response) {
$scope.information = response.data;
debugger
});
Your problem is solved

In angularjs, how do I determine the location of a div based on data in the scope

I am attempting to make a calendar in angular.js.
Let's say I have the following data in the scope:
$scope.events = [{"date":"2016-07-23","name":"Bob's Birthday"},
{"date":"2016-07-24","name":"Doc appt"},
{"date":"2016-07-25","name":"Date with Shannon"}]
I also have a calendar in the HTML with a div corresponding to each date in the month. How do I go about having each date show the corresponding events.
I am new to angular, and my kneejerk reaction is to have each date div have an attribute in each date div containing the date, and loop through the list of events and append an event-div for each event to the corresponding date div using jQuery. But the issue with this is that when the scope changes, the view wont.
Is there a good way to do this using angular? I know you can have directives that loop through data or be hidden depending on the data, but I can't seem to find anything about using angular to determine the location of a div
You could do something like this:
"use strict";
var app = angular.module("testApp", [], function() {});
app.controller("appCtrl", function($scope) {
$scope.events = [
{ "date": "2016-07-23", "name": "Bob's Birthday" },
{ "date": "2016-07-24", "name": "Doc appt" },
{ "date": "2016-07-25", "name": "Date with Shannon" }
];
$scope.$watch("events", function(newValue, oldValue) {
console.log("entireScope has changed", newValue, oldValue);
$.each(newValue, function(index, value) {
$("[data-date=" + value.date + "]").html(value.name);
});
}, true);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="testApp">
<div ng-controller="appCtrl" id="appCtrl">
<div class="fc-day fc-widget-content fc-mon fc-past" data-date="2016-07-23"></div>
</div>
</body>
But the issue with this is that when the scope changes, the view wont.
$watch is provided by angularjs specifically to deal with this situation.
You can use $watch on your $scope.events. Whenever there will be a change in $scope.events, it will run a function defined by you. You can place your logic inside that function that will update your calendar accordingly.
See this Plunker that I've created for you.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.events = [{"date":"2016-07-23","name":"Bob's Birthday"},
{"date":"2016-07-24","name":"Doc appt"},
{"date":"2016-07-25","name":"Date with Shannon"}];
$scope.changeEvent = function() {
var nameDOM = document.getElementById("name");
var dateDOM = document.getElementById("date");
var event = {
"date": dateDOM.value,
"name": nameDOM.value
};
$scope.events.push(event);
nameDOM.value = dateDOM.value = ""
}
$scope.$watch('events', function() {
alert("hey, events variable has changed! It's time to put some logic here that will update the calendar accordingly");
}, true);
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<input id="name" name="name" placeholder="name"/><br>
<input id="date" name="date" placeholder="date"/><br>
<button ng-click="changeEvent()">addEvents</button>
</body>
</html>

Angular custom directive with promise not working

I'm trying to build a directive based on Angular custom filter with promise inside. I tried defining a filter, with the same result.
The issue is that I always get {} as the value, whenever I use a promise.
The following simple example shows the issue very clearly.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.directive('convert', ['$q', function ($q) {
return {
template: '{{convertFunc()}}',
link: function (scope, elem, attrs) {
scope.convertFunc = function () {
var def = $q.defer();
def.resolve('test');
return def.promise.then(function (s) {
return s; // debugger doesn't stop here
}, function (e) {
return e; // debugger doesn't stop here
});
};
}
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="https://code.angularjs.org/1.2.28/angular.js" data-semver="1.2.28"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div data-convert></div>
</body>
</html>
Can you help finding out what am I doing wrong?
Edit
This is the plnkr I used to create the example.
Edit 2
I'm trying to show the result of the promise on a page. In my real code I'm calling a service and then building a string using values from the service.
VS debugger shows that my string is built correctly. But I cannot display it on the page. I'm under the impression, that JS/Angular fails to recognize completion of the promise. I cannot stop on the breakpoints marked above.

Categories

Resources