Link a timestamp to a datetime-local input using ng-model

My challenge is to display an

<input type="datetime-local>
field using the ng-model attribute to represent a timestamp:

<input type="datetime-local" ng-model="object.value">

This is being achieved with:

$scope.object.value = 1433109600000;

Unfortunately, I am encountering an error message in the console: [ngModel:datefmt].

How can I properly link $scope.object.value to the input field? (The timestamp is obtained from a web service within a deeply nested object)

You can view some Plnkr examples here: http://plnkr.co/edit/TGpKVNF1tv0b1h6JPBT8?p=preview

Answer №1

To ensure proper functionality, the variable must be a date object:

$scope.object = {
  name: 'Demo',
  value: new Date(1433109600000)
}

Check out the updated demo here

Alternatively, you can create a directive:

app.directive('bindTimestamp', function () {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attrs, ngModel) {
      ngModel.$formatters.push(function (value) {
        return new Date(value);
      });
    }
  };
});

View the directive demo

Answer №2

In addition to @karaxuna's answer, I would like to provide the complete directive and its testing:

directivesApp.directive('bindTimestamp', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {

            var minDate = attrs.min ? new Date(attrs.min) : null;
            var maxDate = attrs.max ? new Date(attrs.max) : null;

            ngModel.$formatters.push(function (value) {
                var dt = value;
                if (!angular.isDate(dt) && angular.isNumber(dt)) {
                    // It's a timestamp --> needs to be converted to a <Date>
                    dt = new Date(value);
                }
                // truncate 'dt' to second if milliseconds are not to be displayed in input[datetime-local]
                // dt.setMilliSeconds(0);
                // truncate 'dt' to minute if seconds are not to be displayed in input[datetime-local]
                // dt.setSeconds(0);
                return dt;
            });

            // Default validators need to be overriden, otherwise they will always trigger "false" as they expect a <Date> object and not a number.
            var MinMaxValidator = function (modelValue) {
                var selectedDate = angular.timestampToDate(modelValue, scope.truncateSeconds);
                this.validate = function (validateThreshold) {
                    if (angular.isDate(selectedDate)) {
                        return validateThreshold(selectedDate);
                    }
                    return true;
                };
            };

            if (ngModel.$validators.min && minDate !== null) {
                ngModel.$validators.min = function (modelValue) {
                    return new MinMaxValidator(modelValue).validate(function (selectedDate) {
                        return minDate <= selectedDate;
                    });
                };
            }

            if (ngModel.$validators.max && maxDate !== null) {
                ngModel.$validators.max = function (modelValue) {
                    return new MinMaxValidator(modelValue).validate(function (selectedDate) {
                        return maxDate >= selectedDate;
                    });
                };
            }
        }
    };
});

Jasmine test: describe('bindTimestamp : timestamps', function () {

    // 2016-02-19 09:56:51.396ms
    var dt = 1455872211396;

    function buildInputDateElement(inputType) {
        var element = angular.element('<input type="' + inputType + '" ng-model="myDate" bind-timestamp>');
        $compile(element)($scope);
        $scope.$digest();
        return element;
    }

    it('bindTimestamp : input[date]', function () {

        var formattedDate = '2016-02-19';

        /** A timestamp */
        $scope.myDate = dt;
        var element = buildInputDateElement("date");
        expect(element.val()).toEqual(formattedDate);

        //** Already a <Date> */
        $scope.myDate = new Date(dt);
        element = buildInputDateElement("date");
        expect(element.val()).toEqual(formattedDate);
    });

    it('bindTimestamp : input[datetime-local]', function () {

        var formattedDate = '2016-02-19T09:56:51.396';

        /** A timestamp */
        $scope.myDate = dt;
        var element = buildInputDateElement("datetime-local");

        expect(element.val()).toEqual(formattedDate);

        /** Already a <Date> */
        $scope.myDate = new Date(dt);
        element = buildInputDateElement("datetime-local");
        expect(element.val()).toEqual(formattedDate);
    });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In the iOS app when the Ionic HTML5 select keypad is opened, a bug causes the view to scroll upwards and create empty space after tapping the tab

I am currently working with Ionic v1 and AngularJS, utilizing ion tabs: <ion-tabs class="tabs-icon-top tabs-color-active-positive"> <!-- Home Tab --> <ion-tab icon-off="ion-home" icon-on="ion-home" href="#/tab/home"> <ion-nav ...

Accessing attribute value of selected option in AngularJS select element

I have a select tag that displays options, and I want it so that when an option is selected, the value of the data-something attribute is copied into the input element. This is just for demonstration purposes; the actual value should be sent in the form. ...

How can I prevent mouse movement hover effects from activating in a media query?

I have implemented a custom image hover effect for links in my text using mousemove. However, I want to disable this feature when a specific media query is reached and have the images simply serve as clickable links without the hover effect. I attempted ...

Determine whether the browser is being used on an Android or iOS device

Is there a dependable method to alter buttons and text on a mobile site based on whether the user is using an Android or iOS browser? ...

Simplified method for creating Angular templates

Take a look at this code snippet my_app.run( [ '$templateCache' , function( $templateCache ) { var template = "" + "{{ item.name }}" + "<ul ng-if='item.sub'>" + "& ...

Swap out a module with a different one in a node.js environment

In the scenario where a node.js application consists of numerous files referencing a particular module (like underscore), and there is a need to replace that module with another (such as lodash), the typical approach involves globally replacing the names a ...

PubSub.js offers a solution for efficiently managing multiple subscriptions or dealing with multiple callbacks in a more streamlined manner

I am currently exploring the most effective approach for handling a specific scenario. My goal is to establish the following flow: 1.) Obtain configuration data from the server (asynchronously) 2.) Execute doStuff() once the configuration data is receive ...

Dynamically hiding elements within tabs using jQuery

Previously, I created a functionality for handling a single set of tabs. However, as the application has expanded, this functionality is no longer sufficient to accommodate multiple sets of tabs. The initial function looked like this: var iconTabs = func ...

Avoid an excessive number of XHR/AJAX requests when using the Facebook embedded iframe

I am facing an issue with a Bootstrap Carousel that contains multiple social embeds from Facebook, all of which have videos. The problem is evident on this simple jsfiddle due to the Facebook embed. If you visit this page: https://jsfiddle.net/1L95vqn4/, ...

What is the best way to include multiple entries in a select2 form using ajaxform?

select2/3.5.2/ I had to repost this because my initial post was not formatting correctly. The tools in use are: A select2 form field that allows searching through multiple records A bootstrap popup modal containing a form for entering a new record if i ...

The function cannot be invoked. The 'Boolean' type does not have any call signatures. An error has occurred in the computed property of Vue3

Currently, I am working on creating a computed property that checks if an item is in the array. The function I have created returns a boolean value and takes one parameter, which is the item to be checked. isSelected: function (item: MediaGalleryItemTypes) ...

Seamlessly transition between various states within a React component for a fluid user experience

I'm currently working on a simple component structured like this: var component = React.createClass({ render: function(){ if (this.props.isCollapsed){ return this.renderCollapsed(); } return this.renderActive() }, ren ...

Designing a sequential bar graph to visualize intricate data using AmCharts

I received the following response from the server in JSON format: [{ "data1": { "name": "Test1", "count": 0, "amount": 0, "amtData": [ 0,0,0,0 ], "cntData": [ 0,0,0,0 ], "color": "#FF0F00" }, "data2": { ...

Oops! There seems to be a problem with inserting an image using

I am trying to insert multiple images with a loop when clicked. The images are named "0.jpg","1.jpg","2.jpg" etc. To achieve this, I am using an array with all the elements: {name: '1', result: 1, prefecture: "city", photo1: "0.jpg"}, and my l ...

Alert: Prop type error encountered - The prop 'open' must be defined in Snackbar component

Recently, I've been implementing jest snapshot tests into my application. The main focus is on the LoginForm component. render() { return ( ... <DynamicSnack dialogOpen={this.props.dialogOpen} snackOpen={this.props.sna ...

Looking to fill a text field with email addresses by selecting checkboxes for various towers

I have 4 towers and I need checkboxes for each of them. Upon checking any combination of them, the 'txtNotifTo' textbox should be populated with the respective group of email IDs for each tower selected. Could you please assist me in identifying ...

The Timestamp#equals() method may encounter issues when Timestamp is being mapped to or from a Database

I store date and time using DATETIME in my MS SQL Database. When transferring data from Java to the database, I use preparedStatement.setTimestamp(2, insertObj.getTimestamp()); And when retrieving data from the database to Java, I use selectedObj.setTime ...

Share the Nav tag value or name during an OnClick event within ReactJS

I've been facing a minor issue that I just can't seem to figure out - how do I pass a value to my OnClick event? It's crucial for me to pass this value as it corresponds to the options in my menu and is essential for some processes: This is ...

Utilizing Firebase login to integrate with Facebook API

My current setup involves Facebook authentication tied to login, all managed through Firebase. However, I now face the need to make an API call to Facebook using 'me/friends/' endpoint without having to send another request since I am already log ...

Is it possible to create an HTML link that prevents users from navigating back to the previous page or displaying the previous link in their browsing history?

I've been tasked with creating a button on a client's website that links to another page, like Google, for the purpose of assisting someone seeking help in case of an emergency. The challenge is finding a way to prevent the user from easily retur ...