Nathan
Nathan

Reputation: 2387

AngularJS: Why won't ng-click set a variable as a value obtained from ng-repeat?

I'm trying to give an app the ability to set the font for portion of text based on a list of fonts from Google Fonts.

Here's what I have:

<ul ng-init='headerFont="mono"'>
  <li ng-repeat='font in fonts' style='font-family: {{font}};' ng-click='headerFont = font'>{{font}}
  </li>
</ul>

and then later on:

<h1 style='font-family: {{headerFont}};'>Header</h1>

and in the controller in my js file:

$scope.fonts = [...an array of font names...]

Originally, instead of ng-repeat on <li>, I was using:

<select ng-model='headerFont' style='font-family: {{headerFont}};'>
  <option ng-repeat='font in fonts' style='font-family:{{font}};'>{{font}}
  </option>
</select>

And that worked exactly like I wanted it to. But I wanted to try using a scrollable list instead of a drop-down menu because the <select> menu on mobile browsers doesn't support changing fonts of individual options, and it's important to me for the fonts to be able to be previewed before choosing. I figured I could just use ng-click to set the value of headerFont, but it doesn't do anything (no errors show up in the console or anything. Just nothing happens.) Does anyone know why?

Upvotes: 3

Views: 4456

Answers (2)

musically_ut
musically_ut

Reputation: 34288

Each ng-repeat creates a new scope. The ng-click changes the headerFont in its own scope, without touching the headerFont on the top level.

You can create dictionary at the top level to prevent the child scope from kicking in:

<ul ng-init="top = {'headerFont':'mono'}">
 <li ng-repeat='font in fonts' 
     style='font-family: {{font}};' 
     ng-click='top.headerFont = font'>
   {{font}} / {{top.headerFont}}
  </li>
</ul>

Demo: http://plnkr.co/edit/77zesZsBgYpZUDWciY18?p=preview

Upvotes: 2

dfsq
dfsq

Reputation: 193271

The problem is that ngRepeat creates child scope for each iteration, so ngClick actually changes local child headerFont variable.

One possible solution is to explicitly refer parent scope:

var app = angular.module('demo', []);
app.controller('demoController', function($scope) {
    $scope.fonts = ['Arial', 'Times New Roman', 'Verdana', 'mono'];
})
<script data-require="[email protected]" src="https://code.angularjs.org/1.4.3/angular.js" data-semver="1.4.3"></script>

<div ng-app="demo" ng-controller="demoController">
    <h1 style='font-family: {{headerFont}};'>Header</h1>

    <ul ng-init='headerFont="mono"'>
        <li ng-repeat='font in fonts' style='font-family: {{font}};' ng-click='$parent.headerFont = font'>{{font}}</li>
    </ul>
</div>

Upvotes: 8

Related Questions