15

I am unable to call a controller function from inside a custom-template with ui-typeahead:

<input typeahead="val for val in autoComplete($viewValue)"
  typeahead-template-url="searchAutocompleteTpl.html"  
  ng-model="query"/>

<script type="text/ng-template" id="searchAutocompleteTpl.html">
  <span ng-repeat="eqp in match.model.equipment"/>
    <a href="" ng-click="showItem(eqp.model)">
      found in: {{eqp.model}}
    </a>
</script>

The problem is that the controller's scope seems to be absent in the template:

showItem(eqp.model)

is never called. I have also tried with:

$parent.showItem(eqp.model)

to no avail.

How can I call a function/value on the controller's scope then?

supercobra
  • 15,810
  • 9
  • 45
  • 51
recalcitrant
  • 939
  • 11
  • 23

4 Answers4

18

I ran into the same problem and had a look at the typeahead code on github to see if that might offer any clues. It appears that there are several directives involved in the creation of the suggestions list and each gets its own child scope.

In other words, your $parent.showItem(eqp.model) was a good attempt, but you didn't go up enough levels. What worked for me was: $parent.$parent.$parent.showItem(eqp.model)

Rogier Pennink
  • 388
  • 1
  • 12
  • 1
    thanks, but do you know why? and where can we see clearly about the structure of the scope. – Awakening Jan 02 '14 at 12:43
  • It took 4 $parent for me to get to the original scope. – ddalex Jun 05 '15 at 11:50
  • 1
    It depends how and where you use it. typeahead clearly introduces an isolated scope somewhere which means you don't get to prototypically inherit from your own parent scopes. This is why you have to use $parent, which is populated by angular even in isolated scopes. If you're using typeahead in your own directive which also defines an isolated scope, then you would need to go up the $parent chain 4 times to get to your base scope. Of course at this point you may want to start reconsidering your code. The point of an isolated scope is that it can be reused because it doesn't depend on a parent. – Rogier Pennink Jun 09 '15 at 08:11
  • @Awakening: The typeahead has several nested child scopes, usually one for the popup and one for each result within that dropdown. You can use **AngularJS Batarang** to inspect your scope structure at run-time. It's an extension for the Developer Tools of Google Chrome. – user1438038 Mar 11 '22 at 14:22
2

I also have same problem. I'm not sure but its working.

You can use double $parent instead of single.

e.g. $parent.$parent.showItem(eqp.model)

Gynteniuxas
  • 7,035
  • 18
  • 38
  • 54
pravin dabhi
  • 302
  • 1
  • 11
1

The solution of your problem is to initiate an object in your template controller scope like this:

$scope.typeaheadObject = {
   query : '',
}

now in your form you will need to change your ng-model with:

ng-model="typeaheadObject.query'

This will create the object typeaheadObject in all your controller if you don't re-initiate it in one of your controller. So when you will want to access to the content of the object in one of this controller you will just have to do for example:

console.log($scope.typeaheadObject.query)

This is a classical issue in angularJs. You only can access and modify a parent scope if the variable is stock in an object

Finally you have to use a '.' in your ng-model. This will permit your ui-bootstrap module and your own module to share their scope with the object.

I just did an example on plunker to be sure you understand well the issue.

http://plnkr.co/edit/4YWNMagm571Gk2DrCERX?p=preview

Have a good day :)

stephanec
  • 325
  • 1
  • 14
1

It worked for me after adding 4 parents. $parent.$parent.$parent.$parent.