Search code examples
javascripthtmlcssangularjsjqlite

Removing a tag from an appended element by its class/id


I have the following code, and I cant get the previously appended text "You are now editing this" removed from the DOM when the user moves to edit something else. Any advice would be much appreciated. I am trying to avoid using jQuery too as I think it can be achieved with jQLite. Many thanks.

var editApp = angular.module('editApp', ['ngRoute']);

editApp.directive('editInPlace', function() {
  return {
    restrict: 'EA',
    scope: {
      value: '=editInPlace'
    },
    template: '<span ng-click="edit()" ng-bind="value"></span><input ng-model="value"></input>',
    link: function($scope, element, attrs) {
      // Let's get a reference to the input element, as we'll want to reference it.
      var inputElement = angular.element(element.children()[1]);

      // This directive should have a set class so we can style it.
      element.addClass('edit-in-place');

      // Initially, we're not editing.
      $scope.editing = false;

      // ng-click handler to activate edit-in-place
      $scope.edit = function() {
        $scope.editing = true;

        // We control display through a class on the directive itself. See the CSS.
        element.addClass('active');
        element.append('<b class="yaet">You are now editing this</b>');
        // And we must focus the element. 
        // `angular.element()` provides a chainable array, like jQuery so to access a native DOM function, 
        // we have to reference the first element in the array.
        inputElement[0].focus();
      };

      // When we leave the input, we're done editing.
      inputElement.prop('onblur', function() {
        $scope.editing = false;
        element.removeClass('active');
        element.remove('.yaet'); // This is bit that fails
      });
    }
  };
});

editApp.controller('ContactsCtrl', function($scope) {
  $scope.contacts = [{
    number: '+25480989333',
    name: 'sharon'
  }, {
    number: '+42079872232',
    name: 'steve'
  }];
});
.edit-in-place span {
  cursor: pointer;
}
.edit-in-place input {
  display: none;
}
.edit-in-place.active span {
  display: none;
}
.edit-in-place.active input {
  display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.28/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.28/angular-route.min.js"></script>
<div ng-app="editApp">
  <div ng-controller="ContactsCtrl">
    <h2>Contacts</h2>
    <br />
    <ul>
      <li ng-repeat="contact in contacts">
        <span edit-in-place="contact.number"></span> |
        <span edit-in-place="contact.name"></span>
      </li>
    </ul>
    <br />
    <p>Here we repeat the contacts to ensure bindings work:</p>
    <br />
    <ul>
      <li ng-repeat="contact in contacts">
        {{contact.number}} | {{contact.name}}
      </li>
    </ul>

  </div>
</div>


Solution

  • You will have to select .yaet by class and remove them. Since you want to use jqLite, you will have to select elements manually, for example like this:

    inputElement.prop('onblur', function() {
        $scope.editing = false;
        element.removeClass('active');
        angular.element(element[0].querySelector('.yaet')).remove();
    });
    

    var editApp = angular.module('editApp', ['ngRoute']);
    
    editApp.directive('editInPlace', function() {
      return {
        restrict: 'EA',
        scope: {
          value: '=editInPlace'
        },
        template: '<span ng-click="edit()" ng-bind="value"></span><input ng-model="value"></input>',
        link: function($scope, element, attrs) {
          // Let's get a reference to the input element, as we'll want to reference it.
          var inputElement = angular.element(element.children()[1]);
    
          // This directive should have a set class so we can style it.
          element.addClass('edit-in-place');
    
          // Initially, we're not editing.
          $scope.editing = false;
    
          // ng-click handler to activate edit-in-place
          $scope.edit = function() {
            $scope.editing = true;
    
            // We control display through a class on the directive itself. See the CSS.
            element.addClass('active');
            element.append('<b class="yaet">You are now editing this</b>');
            // And we must focus the element. 
            // `angular.element()` provides a chainable array, like jQuery so to access a native DOM function, 
            // we have to reference the first element in the array.
            inputElement[0].focus();
          };
    
          // When we leave the input, we're done editing.
          inputElement.prop('onblur', function() {
            $scope.editing = false;
            element.removeClass('active');
            angular.element(element[0].querySelector('.yaet')).remove();
          });
        }
      };
    });
    
    editApp.controller('ContactsCtrl', function($scope) {
      $scope.contacts = [{
        number: '+25480989333',
        name: 'sharon'
      }, {
        number: '+42079872232',
        name: 'steve'
      }];
    });
    .edit-in-place span {
      cursor: pointer;
    }
    .edit-in-place input {
      display: none;
    }
    .edit-in-place.active span {
      display: none;
    }
    .edit-in-place.active input {
      display: inline-block;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.28/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.28/angular-route.min.js"></script>
    <div ng-app="editApp">
      <div ng-controller="ContactsCtrl">
        <h2>Contacts</h2>
        <br />
        <ul>
          <li ng-repeat="contact in contacts">
            <span edit-in-place="contact.number"></span> |
            <span edit-in-place="contact.name"></span>
          </li>
        </ul>
        <br />
        <p>Here we repeat the contacts to ensure bindings work:</p>
        <br />
        <ul>
          <li ng-repeat="contact in contacts">
            {{contact.number}} | {{contact.name}}
          </li>
        </ul>
    
      </div>
    </div>