omenclature
omenclature

Reputation: 95

Angular expression inside an ng-repeat not being rendered when parent scope referenced

so I'm working on an elastic search implementation in Angular. So far so good but I'm running into a weird situation. Each result has an associated tag(s) that can be user-generated.

Here is my form & input:

<form ng-submit="search($event)" class="queryBuilder ng-pristine ng-valid">
    <input type="text" ng-model="searchQuery" class="ng-pristine ng-untouched ng-valid">
</form>

The results are displaying just fine and so are the tags. The problem comes into play when I click on the tags. Initially, the issue was while inside the repeat, they didn't have access to the above searchQuery model so I simply changed it to target $parent.searchQuery and that worked but dig this, as soon as I did that the expression item.tag no longer worked. Now it's outputting the actual curly brackets and all.

<button ng-repeat="item in items" ng-click="$parent.searchQuery = $parent.searchQuery + ' {{item.tag}}'; search();" class="tag ng-binding ng-scope">Tag Name</button>

I'm very new to Angular, been using jQuery for a billion years so I apologize in advance if I'm missed something very basic. I've searched around and can find scope related material but not expressions inside an ng-repeat clashing with targeting parent scope. Any thoughts? Thanks in advance!

Upvotes: 1

Views: 347

Answers (2)

manzapanza
manzapanza

Reputation: 6215

You could create a method on your controller:

$scope.clickItem = function(item){
    $scope.searchQuery += ' ' + item.category;
    $scope.search();
};

View:

<button ng-repeat="item in items" ng-click="clickItem(item)" class="tag">foundation</button>

Upvotes: 0

Shashank Agrawal
Shashank Agrawal

Reputation: 25797

String literals (searchQuery here in this case) and primitives can not be referenced over the nested scopes in Angular or Javascript. Read a famous tutorial on this https://github.com/angular/angular.js/wiki/Understanding-Scopes

You used $parent which was working initially but when you attached ng-repeat it starts breaking because ng-repeat creates a new scope so now your $parent property is referencing to a different scope.

Regarding how you fix it: define an object in your controller like:

$scope.globalData = {};

Now reference your every ng-model with this object so to avoid the scope problems:

<form ng-submit="search($event)" class="queryBuilder ng-pristine ng-valid">
    <input type="text" ng-model="globalData.searchQuery" class="ng-pristine ng-untouched ng-valid">
</form>

And your ng-repeat to like this:

<button ng-repeat="item in items" ng-click="globalData.searchQuery = globalData.searchQuery + ' {{item.tag}}'; search();" class="tag ng-binding ng-scope">Tag Name</button>

This will reference your search query model with a Javascript Object and Object in Javascript can be referenced by the child instances or in case of Angular, can be referenced in the nested $scope.

Just make sure you put define that gloabalData (or whatever name you like) in a top level controller like one added to <html> or <body> tag so that it's scope can be available throughout the app. And of course, you don't have to use the $parent now :-)

Also, you can clean up your ng-click expression like:

ng-click="globalData.searchQuery = globalData.searchQuery + ' ' + item.tag; search();"

Upvotes: 1

Related Questions