1

I have a directive that makes use of jquery events on the element parameter of the link function, this directive has an input that is binding to a value that is obtained from the main controller of the page, passed through nested directives in a isolated scope , but when changing the value in the input is not reflected in the original object from controller.

The object has the following structure: Invoice 1: - Product 1 - Product 2 Invoice 2: - Product 3 - Product 4

When I change the amount of the invoice, the value is updated in the main controller, but when I change the amount of the product the change is not reflected.

This is my directive, what you should do is that when the user clicks on the value an input appears to be able to edit the value of the model:

eFieldTemplate.html

<div>
<div ng-if="IsMouseIn">
    <input type="text" ng-model="value" class="form-control input-sm" />
</div>
<div ng-if="IsMouseOut"  ng-click="OnMouseClick()">
    {{value}}
</div>
<div ng-if="MouseClick">
    <input  type="text" ng-model="value" class="form-control input-sm" />
</div>

eFieldDirective.js

 angular.module("appDirectives").directive("eField", function () {
    return {
        restrict: "E",
        templateUrl: "eFieldTemplate.html",
        scope: {
            value: "="
        },
        controller: function ($scope) {
            $scope.IsMouseOut = true;
            $scope.IsMouseIn = false;
            $scope.MouseClick = false;
            $scope.OnMouseEnter = function () {
                if (!$scope.MouseClick) {
                    $scope.IsMouseOut = false;
                    $scope.IsMouseIn = true;
                    $scope.MouseClick = false;
                }
            }

            $scope.OnMouseLeave = function () {
                if (!$scope.MouseClick) {
                    $scope.IsMouseOut = true;
                    $scope.IsMouseIn = false;
                    $scope.MouseClick = false;
                }
            }

            $scope.OnMouseClick = function () {
                    $scope.IsMouseOut = false;
                    $scope.IsMouseIn = false;
                    $scope.MouseClick = true;
            }

            $scope.EndEdit = function () {
                $scope.IsMouseOut = true;
                $scope.IsMouseIn = false;
                $scope.MouseClick = false;
            }
        },
        link: function (scope, el, attrs) {
            el.on("mouseenter", function () {
                scope.OnMouseEnter();
                scope.$apply();
            });

            el.on("mousemove", function () {
                scope.OnMouseEnter();
                scope.$apply();
            });

            el.on("mouseleave", function () {
                scope.OnMouseLeave();
                scope.$apply();
            });

            el.on("click", function () {
                scope.OnMouseClick();
                if (el[0].querySelector('input'))
                    el[0].querySelector('input').select();
                scope.$apply();
            });
        }
    };
});

Any Suggestions?

I give the example here: Plunker

UPDATED

I found a solution using ngIf, and is to reference a variable from the parent scope using $ parent.value. Eg.

<Input type="text" ng-model="$parent.value" class="form-control input-sm" />

Or also referring to another object eg.

<input type="text" ng-model="value">
<div ng-if="IsMouseIn">
    <input type="text" ng-model="value">
</div>

Here is the reference link: what is the difference between ng-if and ng-show/ng-hide

Community
  • 1
  • 1
pBlackmouth
  • 60
  • 1
  • 9
  • Not seeing how the code in your question matches the problem you're describing at all – Phil Nov 23 '16 at 00:09

2 Answers2

1

using ng-if makes it create/destroy new html nodes and it seems to be unable to cope with that. change to ng-show and it will work. i also added a body mouse capture so it ends the edit.

<div>
<div ng-show="IsMouseIn">
    <input type="text" ng-model="value" class="form-control input-sm" />
</div>
<div ng-show="IsMouseOut"  ng-click="OnMouseClick()">
    {{value}}
</div>
<div ng-show="MouseClick">
    <input  type="text" ng-model="value" class="form-control input-sm" />
</div>

view plunker

joe
  • 1,359
  • 14
  • 19
  • Thank you very much! Works perfect!! – pBlackmouth Nov 23 '16 at 00:52
  • Is there any way to continue using ng-if ?, now there is a flicker when showing / hiding each element of the directive, that makes each row grow larger by a fraction of time where the HTML elements are moved. – pBlackmouth Nov 23 '16 at 15:58
  • maybe you could try having just one input field and use ng-class/style to change its look and feel instead. i guess it makes more sense even from a performance point of view since it's less lookups added to the digest cycle. – joe Nov 24 '16 at 00:59
1

If you want to use ng-if not ng-show still, define $scope.values and $scope.config and use like this. To avoid the ng-if problem you should define an object.

    <div>
<div ng-if="config.IsMouseIn">
    <input type="text" ng-model="values.value" class="form-control input-sm" />
</div>
<div ng-if="config.IsMouseOut"  ng-click="OnMouseClick()">
    {{values.value}}
</div>
<div ng-if="config.MouseClick">
    <input  type="text" ng-model="values.value" class="form-control input-sm" />
</div>
Farzad Salimi Jazi
  • 760
  • 10
  • 25