0

I'm using Angular 1.4.7. I didn't set up this site so I'm not sure what information I need to give for this. We're rendering some search filters, but whether or not they're enabled is configured by data retrieved from the server, for example:

$scope.searchFields = {
    "date": true,
    "price": true,
    ...
};

The HTML for a search field ($scope.filter being an individual set of vars for this particular filter, in this case it's just selecting a maximum numeric value):

<div class="limit-group clearfix">
    <span class="detail">Filter Name:</span>
    <div class="filter-select-small">
        <select name="filter" class="custom-select" ng-if="searchFilters.code">
            <option value="">No Max</option>
            <option ng-repeat="(key, value) in filter" value="<%key%>"><%value%></option>
        </select>
        <span class="unavailable" ng-if="!searchFilters.code">Unavailable</span>
    </div>
</div>

There are conditions where the available search fields will change. The select fields, for whatever reason, get replaced by a jQuery plugin called selectbox. I have a function resetFilterStyles() which reattaches the jQuery plugin to the fields, but I'm not sure where to fire it.

Inside of methods defined on $scope the data is being updated using $http.get() but running resetFilterStyles() inside of these anonymous functions does not work, presumably because Angular hasn't processed yet that the data has been updated, so the changes that would be performed by resetFilterStyles() are undone by Angular's updates to the DOM.

I've tried setting a $watch handler but this seems to be the wrong place to run my function as it doesn't appear to take, either (and additionally causes grievous errors within Angular). As someone who doesn't use Angular, I'm not sure where to go from here.

Edit

The reset function:

function resetFilterStyles() {
    // desktop adv filters
    var filterContainer = $('.advance-filter-dropdown');
    $('select',filterContainer).selectbox('detach');
    $('select',filterContainer).selectbox('attach');
    $(".filter-select-small .sbOptions").niceScroll({cursorborder:"",cursorcolor:"#ccc",autohidemode: false});

    // mobile adv filters
    var filterContainer = $('.filter-wizard-mobile');
    $('select',filterContainer).selectbox('detach');
    $('select',filterContainer).selectbox('attach');
    $(".filter-select-small .sbOptions").niceScroll({cursorborder:"",cursorcolor:"#ccc",autohidemode: false});
}
Dissident Rage
  • 2,610
  • 1
  • 27
  • 33
  • Any chance you can upload the rest of your code, preferably to plunker? – dwbartz Sep 19 '16 at 17:27
  • It's a lot, and I don't think I have permission to post unedited code (which it would have to be to maintain my sanity). Is there something more expected? – Dissident Rage Sep 19 '16 at 17:28
  • I'm just curious to see your controller and the reset function you mentioned. As far as not seeing changes, they aren't going to be seen until Angular runs the digest cycle which, unless you tell it explicitly to run, it doesn't know to run. – dwbartz Sep 19 '16 at 17:31
  • The controller definition is extremely long. – Dissident Rage Sep 19 '16 at 17:35
  • Yikes, this is going to be difficult. Normally you want to wrap jQuery in a directive to prevent it leaking elsewhere and then just call $scope.$apply() to force angular to re-evaluate everything. – dwbartz Sep 19 '16 at 17:42
  • I'm not entirely sure how to do that, looking at the documentation. Given more time I'd try to pick this up. – Dissident Rage Sep 19 '16 at 18:37
  • See here: http://stackoverflow.com/questions/16935095/correct-way-to-integrate-jquery-plugins-in-angularjs – dwbartz Sep 19 '16 at 18:58

1 Answers1

2

From the AngularJS perspective, you shouldn't do DOM modifications inside the controller. You should create a directive/component to handle that for you.

But if you really must have that jQuery (legacy projects, for example), you can put your DOM modification into $timeout:

$http.get("url").then(function() {
        $timeout(function() {
          // updateDom
        }, 0);
});
Alexey Soshin
  • 16,718
  • 2
  • 31
  • 40
  • I'm of the perspective AngularJS _shouldn't have been used in the first place_ (and the same with jQuery) so I'm making do with what I've got. I'm not sure if I'm reading the docs correctly about directives/components, but they look like they are not compatible with any of the relevant HTML specifications (then again it's already using `ng-` which isn't compatible, either). – Dissident Rage Sep 19 '16 at 17:27
  • 1
    As I suspected :) Please check given solution and let me know if that works. – Alexey Soshin Sep 19 '16 at 17:30
  • It works, but I am unsure if this is "correct" within the given setup, and without going so far as to start using [more] invalid markup. – Dissident Rage Sep 19 '16 at 17:35
  • 1
    If you are required to strictly adhere to valid html, angular is not your friend. However, you can still call angular elements from either comments or classes. https://docs.angularjs.org/guide/directive Look for the restrict option. Note that this isn't always available and depends on who wrote it. – dwbartz Sep 19 '16 at 17:52