用于isolate指令定义的ngModel

时间:2022-07-01 15:59:04

My Directive with name of datePicker Is On the Input Element, that gets gregorian date from model And converts it to persian date for the end user. with changing date from datePicker(here it is jalali(persian date picker)),it is nessaccery to be converted to gregorian and updates the model.

名称为datePicker的My Directive在输入元素上,从模型获取格里高尔日期并将其转换为最终用户的波斯日期。从datePicker更改日期(这里是jalali(波斯日期选择器)),将nessaccery转换为gregorian并更新模型。

  1. I am not sure from binding type that i used.
  2. 我不确定我使用的绑定类型。

  3. $watch function dont work for me ,it works when page loaded first time.
  4. $ watch函数对我不起作用,它在第一次加载页面时有效。

  5. what is happening for ngModel and dateDirVal attributes in isolated scope?
  6. 孤立范围内的ngModel和dateDirVal属性发生了什么?

  7. the value of ngModelCtrl.$viewValue in gregorianToJalali function equals to NaN. Why?
  8. gregorianToJalali函数中的ngModelCtrl。$ viewValue的值等于NaN。为什么?

my HTML :

我的HTML:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <link href="css/jalali/theme.css" rel="stylesheet" />
    <script src="Scripts/jalali/jalali.js"></script>
    <script src="Scripts/jalali/calendar.js"></script>
    <script src="Scripts/jalali/calendar-setup.js"></script>
    <script src="Scripts/jalali/calendar-fa.js"></script>

    <script src="Scripts/jquery-1.7.1.min.js"></script>
    <script src="Scripts/angular.min.js"></script>
    <script src="Scripts/directive.js"></script>

</head>
<body ng-app="myApp">
    <div ng-controller="myController">
        <input ng-model="dateValue1" date id="id1" />
    </div>
</body>
</html>

and My Directive :

和我的指示:

var app = angular.module('myApp', []);

app.controller('myController', function ($scope) {
    var date = new Date('2014', '06', '03');
    var newdate = new Date(date);

    newdate.setDate(newdate.getDate() + 1);
    $scope.dateValue1 = new Date(newdate);
})
.directive('date', function ($compile) {
    return {
        restrict: 'A',
        require: ['date', '^ngModel'],
        scope: {
            dateDirVal: "=ngModel"
        },
        controller: function ($scope) {

        },
        compile: function (element, attr, linker) {
            return {

                post: function postLink($scope, element, attrs, ctrls) {
                    var myCtrl = ctrls[0], ngModelCtrl = ctrls[1];

                    var inputId = element.attr('id').toString();
                    gregorianToJalali();
                    function gregorianToJalali() {
                        var val = ngModelCtrl.$viewValue;
                        if ($scope.dateDirVal) {
                            var inputValue = $scope.dateDirVal;
                            var gDate = new Date(inputValue);
                            var gY = gDate.getFullYear();
                            var gM = gDate.getMonth();
                            var gD = gDate.getDate();
                            var value = JalaliDate.gregorianToJalali(gY, gM, gD);
                            var jalali = value[0].toString() + "/" + value[1].toString() + "/" + value[2].toString();
                            $scope.dateDirVal = jalali;
                        }
                    }

                    Calendar.setup({
                        inputField: inputId,
                        ifFormat: '%Y/%m/%d',
                        dateType: 'jalali'
                    });

                    element.bind("blur", function (e) {
                        var jDate = element.val().split('/');
                        var value = JalaliDate.jalaliToGregorian(jDate[0], jDate[1], jDate[2]);
                        var gDate = new Date(value[0], value[1], value[2]);
                        ngModelCtrl.$setViewValue(gDate);
                        $scope.dateDirVal = value;
                    });

                    $scope.$watch("dateDirVal", function (newValue, OldValue, scope) {
                        if (newValue) {
                            alert(JSON.stringify(newValue));
                        }
                        //ngModelCtrl.$setViewValue(gDate);
                        //$scope.dateDirVal = value;
                    });

                }
            }
        }
    };
});

1 个解决方案

#1


1  

You could use $parsers and $formatters functions pipelines to do that.

你可以使用$ parsers和$ formatters函数管道来做到这一点。

Functions on $parsers react with DOM changes and its return changes the model. So, you could use a toGregorianDate function to convert persian date and persist the gregorian.

$ parsers上的函数对DOM更改做出反应,其返回更改模型。因此,您可以使用toGregorianDate函数来转换波斯日期并保持格里高利。

Functions on $formatters react with model changes, so, whenever the model changes (including rendering the first time) it will be triggered and its returns are rendered into the DOM. So you could use it to call a toPersianDate function and convert the gregorian into persian date to be rendered to your user.

$ formatters上的函数对模型更改做出反应,因此,只要模型发生更改(包括第一次呈现),它就会被触发并将其返回呈现到DOM中。因此,您可以使用它来调用toPersianDate函数并将gregorian转换为波斯日期以呈现给您的用户。

These functions are listeners, and there are a big caution on compile functions documented on ngModelController DOCs alerting that listenners are supposed to be used on link functions

这些函数是监听器,在ngModelController DOC上记录的编译函数存在很大的警告,警告监听器应该用于链接函数

So I recomend you change a bit your code to look more like that

所以我建议你改变一下你的代码看起来更像那样

.directive('date', function ($compile) {
    return {
        restrict: 'A',
        require: ['date', '^ngModel'],
        scope: {
            dateDirVal: "=ngModel"
        },
        controller: function ($scope) {

        },
        //use link instead of compiler to use DOM listeners
        link: function ($scope, element, attrs, ctrls) {
            var myCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            var inputId = element.attr('id').toString();

            function gregorianToJalali(viewValue) {
                if ($scope.dateDirVal) {
                    var inputValue = $scope.dateDirVal;
                    var gDate = new Date(inputValue);
                    var gY = gDate.getFullYear();
                    var gM = gDate.getMonth();
                    var gD = gDate.getDate();
                    var value = JalaliDate.gregorianToJalali(gY, gM, gD);
                    var jalali = value[0].toString() + "/" + value[1].toString() + "/" + value[2].toString();

                    //The return of a $parsers is what is saved to the model
                    return jalali;
                }
            }

            Calendar.setup({
                inputField: inputId,
                ifFormat: '%Y/%m/%d',
                dateType: 'jalali'
            });

            function jalaliToGregorian(viewValue) {
                var jDate = viewValue.split('/');
                var value = JalaliDate.jalaliToGregorian(jDate[0], jDate[1], jDate[2]);
                var gDate = new Date(value[0], value[1], value[2]);

                //The return of a formmatter is what is rendered on the DOM
                return gDate;
            });

            //with that, jalaliToGregorian will be called every time a user fill the input
            ngModelCtrl.$parsers.unshift(jalaliToGregorian(viewValue))

            //gregorianToJalali will be called every time a model change, converting 
            // gregorian dates and presenting persian date on the view
            ngModelCtrl.$formatters.unshift(gregorianToJalali(viewValue))

        }
    };
});

I tried to not change so much your code to you figure out what happened... so I neither changed your jalaliToGregorian function, but you need to pay attention, that the $parsers function will bind to the model its return... and you are not checking if the inputed date were a persian date at all... if the function return undefined, the model will not be changed... and if return something else, that return will be binded, being a date or not (null can be binded if the inputed date were wrong)

我试图不改变你的代码,你弄清楚发生了什么......所以我既没有改变你的jalaliToGregorian函数,但你需要注意,$ parsers函数将绑定到模型返回...而你不检查输入日期是否完全是波斯日期...如果函数返回undefined,模型将不会被更改...如果返回其他内容,该返回将被绑定,是否为日期(null如果输入日期错误,可以绑定

#1


1  

You could use $parsers and $formatters functions pipelines to do that.

你可以使用$ parsers和$ formatters函数管道来做到这一点。

Functions on $parsers react with DOM changes and its return changes the model. So, you could use a toGregorianDate function to convert persian date and persist the gregorian.

$ parsers上的函数对DOM更改做出反应,其返回更改模型。因此,您可以使用toGregorianDate函数来转换波斯日期并保持格里高利。

Functions on $formatters react with model changes, so, whenever the model changes (including rendering the first time) it will be triggered and its returns are rendered into the DOM. So you could use it to call a toPersianDate function and convert the gregorian into persian date to be rendered to your user.

$ formatters上的函数对模型更改做出反应,因此,只要模型发生更改(包括第一次呈现),它就会被触发并将其返回呈现到DOM中。因此,您可以使用它来调用toPersianDate函数并将gregorian转换为波斯日期以呈现给您的用户。

These functions are listeners, and there are a big caution on compile functions documented on ngModelController DOCs alerting that listenners are supposed to be used on link functions

这些函数是监听器,在ngModelController DOC上记录的编译函数存在很大的警告,警告监听器应该用于链接函数

So I recomend you change a bit your code to look more like that

所以我建议你改变一下你的代码看起来更像那样

.directive('date', function ($compile) {
    return {
        restrict: 'A',
        require: ['date', '^ngModel'],
        scope: {
            dateDirVal: "=ngModel"
        },
        controller: function ($scope) {

        },
        //use link instead of compiler to use DOM listeners
        link: function ($scope, element, attrs, ctrls) {
            var myCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            var inputId = element.attr('id').toString();

            function gregorianToJalali(viewValue) {
                if ($scope.dateDirVal) {
                    var inputValue = $scope.dateDirVal;
                    var gDate = new Date(inputValue);
                    var gY = gDate.getFullYear();
                    var gM = gDate.getMonth();
                    var gD = gDate.getDate();
                    var value = JalaliDate.gregorianToJalali(gY, gM, gD);
                    var jalali = value[0].toString() + "/" + value[1].toString() + "/" + value[2].toString();

                    //The return of a $parsers is what is saved to the model
                    return jalali;
                }
            }

            Calendar.setup({
                inputField: inputId,
                ifFormat: '%Y/%m/%d',
                dateType: 'jalali'
            });

            function jalaliToGregorian(viewValue) {
                var jDate = viewValue.split('/');
                var value = JalaliDate.jalaliToGregorian(jDate[0], jDate[1], jDate[2]);
                var gDate = new Date(value[0], value[1], value[2]);

                //The return of a formmatter is what is rendered on the DOM
                return gDate;
            });

            //with that, jalaliToGregorian will be called every time a user fill the input
            ngModelCtrl.$parsers.unshift(jalaliToGregorian(viewValue))

            //gregorianToJalali will be called every time a model change, converting 
            // gregorian dates and presenting persian date on the view
            ngModelCtrl.$formatters.unshift(gregorianToJalali(viewValue))

        }
    };
});

I tried to not change so much your code to you figure out what happened... so I neither changed your jalaliToGregorian function, but you need to pay attention, that the $parsers function will bind to the model its return... and you are not checking if the inputed date were a persian date at all... if the function return undefined, the model will not be changed... and if return something else, that return will be binded, being a date or not (null can be binded if the inputed date were wrong)

我试图不改变你的代码,你弄清楚发生了什么......所以我既没有改变你的jalaliToGregorian函数,但你需要注意,$ parsers函数将绑定到模型返回...而你不检查输入日期是否完全是波斯日期...如果函数返回undefined,模型将不会被更改...如果返回其他内容,该返回将被绑定,是否为日期(null如果输入日期错误,可以绑定

相关文章