0

Please help me in this issue. Following is the the code.

HTML:

<div ng-controller="ctrl"><a href="{{ link }}">click here</a></div>

JS:

app.controller('ctrl', function($scope) {
  $scope.true_link = "http://google.com";
  $scope.link = "{{ true_link }}";
});

Result:

<div ng-controller="ctrl"><a href="{{ true_link }}">click here</a></div>

Expectation:

<div ng-controller="ctrl"><a href="http://google.com">click here</a></div>

Replace {{ link }} by {{ true_link }} in HTML will solve this problem. But I have to use this way. How can I evaluate expression in $scope.link content again? Please help me. Thanks.


Update

Look like facebook, I have two wall pages: User page and Actor page. They have same template structure and process (append, remove element etc...) after bussiness function such as changeAvatar(), changeCover(), post() etc... So I create 'homepage' based directive:

JS

app.directive('homepage', function() {
  return {
    restrict: 'A',
    templateUrl: 'homepage.html',
    controller: 'homepageCtrl'
  };
});

app.controller('homepageCtrl', function($scope) {
  $scope.changeAvatar() = ...;
  $scope.post() = ...;
});

and two extend controllers:

app.controller('userCtrl', function($scope, $http) {
  $http.({...}).success((data){ $scope.username = data.username })

  $scope.menu = [
    {
      title: "foo-user"
      link: "/u/{{ username }}/foo-user"
    }
    {
      title: "bar-user"
      link: "/u/{{ username }}/bar-user"
    }
  ]
});

app.controller('actorCtrl', function($scope) {
  $http.({...}).success((data){ $scope.actorname = data.actorname })

  $scope.menu = [
    {
      title: "foo-actor"
      link: "/u/{{ actorname }}/foo-actor"
    }
    {
      title: "bar-actor"
      link: "/u/{{ actorname }}/bar-actor"
    }
  ]
});

HTML

homepage.html

<section>
  <header>
    <ul class="menu">
      <li ng-repeat="_menu in menu">
        <a href="{{ _menu.link }}">
          {{ _menu.title }}
        </a>
      </li>
    </ul>
  </header>
  <main>
    content...
  </main>
</section>

User page:

<div homepage ng-controller="userCtrl"></div>

Actor page:

<div homepage ng-controller="actorCtrl"></div>

Two pages menu has same HTML structure & effect, but differ in items. I wanna define menu item in extended controller (userCtrl, actorCtrl) and print them by ng-repeat. The problem is evaluate $scope.menu.link content.


Solution

I found solution: using $scope.$eval (https://docs.angularjs.org/guide/expression).

In userCtrl, the $scope.menu[i].link is dynamic content because included username - received from ajax call. I can update $scope.menu[i].link in $http.success() by using foreach. But I think using $scope.$eval help me auto update wherever I want easier.

So, the code is:

JS

app.controller('userCtrl', function($scope, $http) {
  $http.({...}).success((data){ $scope.username = data.username })

  $scope.menu = [
    {
      title: "foo-user"
      link: "'/u/' + username + '/foo-user'"
      show: 'true'
    }
    {
      title: "bar-user"
      link: "'/u/' + {{ username }} + '/bar-user'"
      show: 'username == "lorem"'
    }
  ]
});

HTML

homepage.html

<section>
  <header>
    <ul class="menu">
      <li 
        ng-repeat="_menu in menu"
      >
        <a 
          ng-href="{{$parent.$eval(_menu.link)}}"
          ng-show="$parent.$eval(_menu.show)"
        >
          {{_menu.title}}
        </a>
      </li>
    </ul>
  </header>
  <main>
    content...
  </main>
</section>
Tri Truong
  • 48
  • 7

4 Answers4

2

Create a directive, and use $eval to parse the expression:

 app.directive('a', function (){
       return {
            restrict : 'E',
            link: function(scope, element, attr){
                  element.attr('href',scope.$eval(attr.href));
            }
       }
 });
Michael Kang
  • 52,003
  • 16
  • 103
  • 135
1
app.controller('ctrl', function($scope) {
   $scope.true_link = "http://google.com";
   $scope.link =  $scope.true_link; // you need a copy of `$scope.true_link` here
});

<div ng-controller="ctrl"><a ng-href="link">click here</a></div>
Kalhan.Toress
  • 21,683
  • 8
  • 68
  • 92
0

$scope.link = "{{ true_link }}"; this is just a string, nothing else, so it will render as such.

Don't be confused by the curly brackets.

You can complicate things by using $compile, eval, etc... or you can simply assign the true_link value to the link variable.


UPDATE

You have a problem in your ng-repeat directive. This:

<li ng-repeat="_menu in menu">
    <a href="{{ menu.link }}">{{ menu.title }}</a>
</li>

Should be this (note _menu):

<li ng-repeat="_menu in menu">
    <a href="{{ _menu.link }}">{{ _menu.title }}</a>
</li>

Also, there's no need to use templating in your controller, so this:

$scope.menu = [
{
  title: "foo-user"
  link: "/u/{{ username }}/foo-user"
}
{
  title: "bar-user"
  link: "/u/{{ username }}/bar-user"
}
] 

can be this:

$scope.menu = [
{
  title: "foo-user"
  link: "/u/" + $scope.username + "/foo-user"
}
{
  title: "bar-user"
  link: "/u/" + $scope.username + "/bar-user"
}
] 
Shomz
  • 37,421
  • 4
  • 57
  • 85
  • You're welcome. I think all the issues are addressed in my update. – Shomz Dec 25 '14 at 12:20
  • Thank you Shomz so much for spending time on my problem. I wanna the the link has dynamic content. And I found solution: using $scope.$eval. I updated the solution in the question. – Tri Truong Dec 25 '14 at 13:38
  • 1
    You're welcome. Yes, I mentioned eval in my original answer. But be aware of its negative sides: http://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea – Shomz Dec 25 '14 at 13:44
0

Why do you want to use {{link}} instead of {{true_link}}? What exactly the issue you've run into that "you have to use this way"? If you can explain this in details, may we can figure out a better solution.

Ivan Wang
  • 460
  • 4
  • 3