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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.