Renne Rocha
Renne Rocha

Reputation: 1255

Hide div with AngularJS with Django-rendered template

I have a HTML form rendered by Django template tag and I want to manipulate it using AngularJS.

In my template (not rendered) I have:

<html>
   <body>
       {{ form.as_p }}
   </body>
</html>

This is how Django renders this template:

<html>
   <body>
      <form>
        <div id="div_id_street" class="ctrlHolder ">
        <label for="id_street">
            Street<span>*</span>
        </label>
        <input id="id_street" type="text" class="textInput textinput" name="street" maxlength="32">
        </div>
      </form>
   </body>
</html>

I want to hide the div div_id_street, but I am not able to add the ng-show or ng-hide directive in my HTML because of the way that Django generates the HTML code.

Is it possible inside an AngularJS controller to show/hide this div?

Thank you!

Upvotes: 1

Views: 1247

Answers (3)

Renne Rocha
Renne Rocha

Reputation: 1255

I was wrong. It is possible to change the template of a Django rendered form.

When defining a django form, I am able to change the widget of each fiels, so I can put the Angular directives in the widget.

For example:

# forms.py
class MyForm(forms.Form):
    street = forms.CharField(max_length=80, 
        widget=forms.TextInput(attrs={
            'ng-model': 'street',
            'ng-show': 'false',
            'ng-change': 'validateStreet()',})
        )

This will be rendered as:

<div id="div_street" class="ctrlHolder">
    <label for="id_street">Street</label>
    <input ng-model="street" name="street" maxlength="80" ng-change="validateStreet()"
      ng-show="false" type="text" class="textInput textinput ng-valid ng-dirty"
      id="id_street">
</div>

So in my controller I can manipulate this whole field.

Upvotes: 4

Mark Rajcok
Mark Rajcok

Reputation: 364717

Is it possible inside an AngularJS controller to show/hide this div?

Yes, but this "goes deep against the Angular way" -- Misko. Inject $element, then use selectors to find and manipulate. $element is set to the element that your controller is defined on.

function MyCtrl($scope, $element) {
  $scope.show = false;
  $scope.$watch('show', function (value) {
    if (value) {
        $element.find('#div_id_street').show();
    } else {
        $element.find('#div_id_street').hide();
    }
  })
}

Fiddle -- in this fiddle I used ng-controller.

Upvotes: 2

Caio Cunha
Caio Cunha

Reputation: 23394

If you can't modify the template, neither add a class to that specific DIV to add it a ng-show, than you should create a directive to handle this DOM manipulation. You shouldn't do DOM manipulation from within a controller. As stated by the DOCs,

Do not use controllers for:

  • Any kind of DOM manipulation — Controllers should contain only business logic. DOM manipulation—the presentation logic of an application—is well known for being hard to test. Putting any presentation logic into controllers significantly affects testability of the business logic. Angular offers databinding for automatic DOM manipulation. If you have to perform your own manual DOM manipulation, encapsulate the presentation logic in [directives]http://docs.angularjs.org/guide/directive).
  • ...

I would suggest you to $watch the property you need and manually show/hide the element from inside the link function of a directive.

Upvotes: 2

Related Questions