Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Umbraco7 new backoffice section, edit date field, AngularJS

I'm trying to create an edit screen for a new section in the back office. I've followed various tutorials on how to go about this and it is working fine for normal text fields.

However, my model has 2 date fields as part of it and I would like to put in some date pickers for them. I cannot for the life of me get them to work. I've tried hooking into bootstrap and using Bootstrap-DatePicker to turn text input's into date time pickers but to no avail.

What's more annoying is that if I use input types of date, then the create screen works no problem, with date pickers. However due to the version of AngularJs within Umbraco, the edit screen does not bind correctly hence trying to find a way around it.

I am using the AngularJS approach to creating the view.

Any help on how I can achieve this would be greatly appreciated.

Links:

Main tutorial

Bootstrap-DatePicker help documents

---- The above question was posted on the our.Umbraco.org forum but has not had a response so I thought I would ask you helpful folk here. ----

Further information,

I've tried to do something like this:

Plunker Example of a possible work around

However, it doesn't seem to work when implemented in Umbraco. I am getting an error saying that Moment is not found yet when I examine the page I can see the following line exists in it:

<script src="http:////cdnjs.cloudflare.com/ajax/libs/moment.js/2.1.0/moment.min.js"></script> 

I would paste the entire Plunker example here but the example itself works fine. It just doesn't work when I use it within my Umbraco Plugin code.

I'm at a complete loss right now. Ideally I would like some sort of artificial "date picker" but that currently doesn't seem to be a feasible option so the Plunker approach was my next thought.

Thanks in advance

Nik

like image 394
Pheonyx Avatar asked May 15 '15 11:05

Pheonyx


1 Answers

I came across this issue a while ago and I resorted to creating a custom angular controller that is essentially a copy of the default Umbraco Umbraco.PropertyEditors.DatepickerController from umbraco.controllers.js.

Create a new file called datepicker.controller.js in your plugin folder and paste in the following code:

angular.module("umbraco").controller("Custom.DatepickerController",
    function ($scope, notificationsService, assetsService, angularHelper, userService, $element) {

        //lists the custom language files that we currently support
        var customLangs = ["pt-BR"];

        //setup the default config
        var config = {
            pickDate: true,
            pickTime: false,
            pick12HourFormat: false,
            format: "dd/MM/yyyy"
        };

        //handles the date changing via the api
        function applyDate(e) {
            angularHelper.safeApply($scope, function () {
                // when a date is changed, update the model
                if (e.localDate) {
                    if (config.format == "yyyy-MM-dd hh:mm:ss") {
                        $scope.criteria[$element.attr('id')] = e.localDate.toIsoDateTimeString();
                    }
                    else {
                        $scope.criteria[$element.attr('id')] = e.localDate.toIsoDateString();
                    }
                }
            });
        }

        //get the current user to see if we can localize this picker
        userService.getCurrentUser().then(function (user) {

            assetsService.loadCss('lib/datetimepicker/bootstrap-datetimepicker.min.css').then(function () {
                var filesToLoad = ["lib/datetimepicker/bootstrap-datetimepicker.min.js"];

                //if we support this custom culture, set it, then we'll need to load in that lang file
                if (_.contains(customLangs, user.locale)) {
                    config.language = user.locale;
                    filesToLoad.push("lib/datetimepicker/langs/datetimepicker." + user.locale + ".js");
                }

                assetsService.load(filesToLoad).then(
                    function () {
                        //The Datepicker js and css files are available and all components are ready to use.

                        // Open the datepicker and add a changeDate eventlistener
                        $element.find("div:first")
                            .datetimepicker(config)
                            .on("changeDate", applyDate);

                        if ($scope.criteria[$element.attr('id')]) {
                            //manually assign the date to the plugin
                            $element.find("div:first").datetimepicker("setValue", $scope.criteria[$element.attr('id')]);
                        }

                        //Ensure to remove the event handler when this instance is destroyted
                        $scope.$on('$destroy', function () {
                            $element.find("div:first").datetimepicker("destroy");
                        });
                    });
            });
        });
    });

Include a reference to the new file in your package.manifest as follows:

{
    javascript: [
        '~/App_Plugins/Custom/datepicker.controller.js'
    ]
}

Then add an input to your view and decorate the containing div with an ng-controller attribute referencing your new controller (Custom.DatepickerController in this case).

<div class="control-group umb-control-group">
    <div class="umb-el-wrap">
        <label class="control-label">From date</label>
        <div class="controls controls-row">
            <div class="umb-editor umb-datepicker" ng-controller="Custom.DatepickerController" id="from">
                <div class="input-append date datepicker" style="position: relative;">
                    <input name="from" data-format="dd/MM/yyyy" type="text" ng-model="criteria.from" />
                    <span class="add-on">
                        <i data-date-icon="icon-calendar"></i>
                    </span>
                </div>
            </div>
        </div>
    </div>
</div>

I made a few customisations to the controller because I wanted to bind my form to a criteria object. You might want to change a few things in order to get it working in the way you want but this should at least give you a starting point.

like image 52
Rob Purcell Avatar answered Sep 21 '22 05:09

Rob Purcell