0

I have Angular directive. Something like multiselect with search. I want to clear query after click on clear icon. Here is the code:

Template:

<div multiselect>
    <ul role="container">
        <li ng-repeat="(k,v) in ::propertyModel.getAllowedValues()" ng-show="isSelected(k);">
            {{v}}
            <span class="icon-close" ng-click="handleOptionRemove(k);" ng-show="!singleSelect"></span>
        </li>
    </ul>
    <div role="opener" class="icon-plus"></div>
    <div role="dropdown" class="closed">
        <div role="search">
            <span class="icon-magnifier"></span>
            <span class="icon-close" ng-click="handleSearchClear();"></span>
            <input type="text" placeholder="Type to search">
        </div>
        <ul role="options">
            <li ng-repeat="(k,v) in ::propertyModel.getAllowedValues()" ng-show="!isSelected(k) && found(k);" ng-click="handleOptionSelect(k);">{{v}}</li>
            <li disabled ng-show="foundItems.length === 0 && queryString !== ''">There is no results found</li>
        </ul>
    </div>
</div>

Directive:

var input= element.find('input');

[...]
function handleSearchInput(){
    scope.foundItems= [];
    scope.queryString= input[0].value.toLocaleUpperCase();
    for(var o in allowedValues) if(allowedValues.hasOwnProperty(o))
        if(allowedValues[o].toLocaleUpperCase().indexOf(scope.queryString)!== -1)
            scope.foundItems.push(o);
    scope.$apply();
}

[...]

scope.handleSearchClear = function(){
    input[0].value='';
    input.triggerHandler('input');
};

[...]
input.bind('input', handleSearchInput);

After click i have

Error: [$rootScope:inprog] $apply already in progress[...]

on console.

How can i properly 'clear' this input's value?

3
  • 1
    Where's the directive defined in the HTML? Why not have an ngModel on the input and then clear it via $scope? Commented Aug 18, 2015 at 14:33
  • Directive is on higher DOM element. Thi is a piece of HTML used by directive. Everything works fine instead of this clear thing. Ok, added almost complete template Commented Aug 18, 2015 at 14:35
  • Use $timeout instead of calling $apply() Commented Aug 18, 2015 at 14:38

2 Answers 2

1

Here's what I do in Jasmine tests to clear an element, perhaps this will be helpful:

var myInput = input[0]; // get the input somehow
angular.element(myInput).val('').trigger('input');

I do agree with tymeJV's suggestion to work from a model when possible. Then you'd end up with something like this:

$scope.model.myfieldval = '';
$scope.model.someOtherFieldVal = '';
$scope.form.myFormName.$setPristine();

Hope this is helpful.

Sign up to request clarification or add additional context in comments.

Comments

0

Ok, it seems that i was jumped outside Angular context.

I was used handleSearchInput function in event callback fired by Angular itself and it was trigered with Angular's context, then i was forced this function with standard javascript context. Or something like that ;)

Anyway there is a solution.

function handleSearchInput () {
    scope.$apply(function () {   //force Angular context (and scope)
        doSearch();
    });
}

function doSearch () {
    scope.foundItems = [];
    scope.queryString = input[0].value.toLocaleUpperCase();
    for (var o in allowedValues) if (allowedValues.hasOwnProperty(o)) {
        if (allowedValues[o].toLocaleUpperCase().indexOf(scope.queryString) !== -1) {
            scope.foundItems.push(o);
        }
    }
}

scope.handleSearchClear = function () {
    //always in context because of existing in scope
    input[0].value = '';
    doSearch();
};

input.bind('input', handleSearchInput);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.