Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 1.5 Component: passing a function

Is it possible to passing a function to a component and call this function inside the component passing a parameter?

Example:

List of posts

<post-list posts="blog.posts"
           loading="blog.loadingPosts"
           get-post-url="blog.getPostUrl" 
           is-user-authenticate="blog.user">
</post-list>

getPostUrl is a function (inside the container controller):

const getPostUrl = (postId) => {
    const protocol = $location.protocol();
    const host = $location.host();
    const port = $location.port();

    return protocol + "://" + host + "" + (port !== 80 ? ":" + port : "") + "/blog/post/" + postId;
};

List of posts: component

const PostList = {
  "bindings": {
    "posts": "<",
    "loading": "<",
    "getPostUrl": "&", //Function getPostUrl
    "isUserAuthenticate": "<"
  },
  "template": `<div>
                <div class="col-md-9 text-center" data-ng-if="$ctrl.loading">
                  <i class="fa fa-spinner fa-spin fa-2x"></i>
                </div>

                <div class="col-md-9 posts" data-ng-if="!$ctrl.loading">
                  <div data-ng-repeat="post in $ctrl.posts">
                    <post creation-date="{{post.creationDate}}"
                          content="{{post.content}}"
                          post-url="{{$ctrl.getPostUrl(post.creationDate)}}"
                          is-user-authenticate="$ctrl.user">
                    </post>
                  </div>
                </div>
              </div>`,
   "transclude": false
};

 angular
  .module("blog")
  .component("postList", PostList);

In this line:

post-url="{{$ctrl.getPostUrl(post.creationDate)}}" I want to call the function passing a parameter and this function is returning a string.

In post component (not PostList) the postUrl is a string attribute @.

But... Is not working!

angular.js:13550 Error: [$interpolate:interr] Can't interpolate: {{$ctrl.getPostUrl(post.creationDate)}} TypeError: Cannot use 'in' operator to search for 'blog' in 1459329888892 Error Link

Is it possible to do it? And how?

Thank you so much!

like image 782
Aral Roca Avatar asked Apr 27 '16 08:04

Aral Roca


Video Answer


2 Answers

If you want to call the function from inside a component and have it return a value then you need two-way binding:

"bindings": {
  "posts": "<",
  "loading": "<",
  "getPostUrl": "=", // <-- two-way binding
  "isUserAuthenticate": "<"
},

However, this is probably not very good idea. Consider passing data to component rather than making component request data from outside. This will make much better isolated component.

like image 185
dfsq Avatar answered Sep 18 '22 20:09

dfsq


You can pass functions to components, but you must define the function arguments as object with the correct arguments names as its keys. example:

<post-list posts="blog.posts"
           loading="blog.loadingPosts"
           get-post-url="blog.getPostUrl(postId)" 
           is-user-authenticate="blog.user">
</post-list>

const PostList = {
 "bindings": {
  "posts": "<",
  "loading": "<",
  "getPostUrl": "&", //Function getPostUrl
  "isUserAuthenticate": "<"
 },
 "template": `<post creation-date="{{post.creationDate}}"
                      content="{{post.content}}"
                      post-url="{{$ctrl.getPostUrl({postId:post.creationDate})}}">
                </post>
like image 45
Doron Avatar answered Sep 19 '22 20:09

Doron