1
\$\begingroup\$

I'm new to AngularJS, coming from a jQuery background and I have a situation I've solved but only by including jQuery in an AngularJS function. Something just doesn't feel right doing this and I was hoping someone could tell me if there's a better way. (This is all code I have inherited and have amended to enable new functionality)

I have 2 checkboxes, let's call them 'Notary' and 'Login'. If I enable Notary, then Login must get enabled and also disabled so the user can't uncheck it.

The ASPX looks like:

 <label class="typ3">Enable INKWRX Login:</label>
 <dw-checkbox class="notarylogin" name="UserHasPassword" ng-model="user.Details.HasPassword" ></dw-checkbox>

<label class="typ3">Notary:</label>
<dw-checkbox name="notary" id="notary" ng-model="user.ExtraData.userPermissions.notary.allowed" ng-click="amendNotary(user.ExtraData.userPermissions.notary.allowed)"></dw-checkbox>

When the dw-checkbox directive is invoked, it renders a checkbox input element for each dw-checkbox tag like this:

 //this directive adds behaviour for showing ticks and cross images in viewMode and an editable checkbox in editmode
    app.directive("dwCheckbox", function ($rootScope) {
        return {
            restict: 'E',
            require: 'ngModel',
            template: '<input name="name" type="checkbox" ng-model="model" />',
            scope: {
                model: '=ngModel',
                name: '=name'
            },
            link: function (scope, element, attrs, ngModel) {

                //render the field according to the mode and the current value of the model
                function render() { ...does the rendering..}

and my amendNotary function which does the checkbox disabling looks like this (I amended another directive to add an inklogin class to the Login checkbox):

$scope.amendNotary = function(value) {
       if (value === true) {
           $scope.user.Details.HasPassword = true;
           $('.inklogin').attr('disabled', true);
       } else {
           $scope.user.SignatureText = "Signature:";
           $('.inklogin').attr('disabled', false);
       }
    }

Is there an obvious cleaner way of doing this, or is mixing jQuery with Angular generally regarded as okay?

\$\endgroup\$
  • \$\begingroup\$ Why not use bindings to enable and disable inklogin based on the current $scope? There is no reason to do so in your current example, no \$\endgroup\$ – Icepickle Aug 14 '17 at 9:51
  • \$\begingroup\$ I tried adding ng-disabled="user.ExtraData.userPermissions.notary.allowed" to the login checkbox on the aspx but since that is not an input element and the checkbox only gets rendered later, it doesn't do anything. Or did you mean something else? \$\endgroup\$ – BMills Aug 14 '17 at 10:12
1
\$\begingroup\$

Is there an obvious cleaner way of doing this [?]

Without knowing where the element(s) with class name inklogin exist, it can only be presumed that it exists as a child of the element with ng-controller="controller" (or however the controller is named). If that is incorrect, please update your post to include that HTML output (from the ASPX code).

Given the presumption above, jQuery can be eliminated by adding ng-disabled (bound to user.ExtraData.userPermissions.notary.allowed) to the input with class inklogin. Bearing in mind that you stated you attempted this, perhaps there was something wrong with the setup. Below is a working example of this:

angular.module('app', [])
  .controller('ctrl', function($scope) {
    $scope.user = {
      Details: {},
      SignatureText: ''
    };
    $scope.amendNotary = function(value) {
      if (value === true) {
        $scope.user.Details.HasPassword = true;
      } else {
        $scope.user.SignatureText = "Signature:";
      }
    };
  }).directive("dwCheckbox", function($rootScope) {
    return {
      restict: 'E',
      require: 'ngModel',
      template: '<input name="name" type="checkbox" ng-model="model" />',
      scope: {
        model: '=ngModel',
        name: '=name'
      },
      link: function(scope, element, attrs, ngModel) {

        //render the field according to the mode and the current value of the model
        function render() {};
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <label class="typ3">Enable INKWRX Login:</label>
  <dw-checkbox class="notarylogin" name="UserHasPassword" ng-model="user.Details.HasPassword"></dw-checkbox>

  <label class="typ3">Notary:</label>
  <dw-checkbox name="notary" id="notary" ng-model="user.ExtraData.userPermissions.notary.allowed" ng-click="amendNotary(user.ExtraData.userPermissions.notary.allowed)"></dw-checkbox>

  <h4>Signature Text:</h4>
  <div ng-bind="user.SignatureText"></div>
  Element with class "inklogin":
  <input type="checkbox" class="inklogin" ng-disabled="user.ExtraData.userPermissions.notary.allowed" />
</div>

or is mixing jQuery with Angular generally regarded as okay?

Generally it is acceptable, though each library requires extra resources (e.g. download size, time, etc.). There are whole websites about removing the need for jQuery, like http://youmightnotneedjquery.com/. if you were working on a team, some teammates might prefer to have as few libraries as possible

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.