Konrad Garus
Konrad Garus

Reputation: 54005

Method definition as result of function call in ClojureScript

Here's a sample piece of JS for Knockout:

function AppViewModel() {
    this.firstName = ko.observable('Bob');
    this.lastName = ko.observable('Smith');
    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);
}

In case you're unfamiliar with KO, each field on AppViewModel becomes a function (i.e. ko.observable and ko.computed each return a function. Also note that fullName depends on both functions.

How can I rewrite this to ClojureScript?

One thing to try is:

(deftype AppViewModel [firstName lastName]
  Object
  (fullName [this] (.computed js/ko (str (firstName) " " (lastName)))))

(defn my-model [first last]
  (AppViewModel. 
    (.observable js/ko "Bob") 
    (.observable js/ko "Smith")))

It doesn't work though, since fullName becomes a function that calls ko.computed. That is, it compiles to:

my_namespace.AppViewModel.prototype.fullName = function() {
  return ko.computed([cljs.core.str(this.firstName.call(null)), cljs.core.str(" "), cljs.core.str(this.lastName.call(null))].join(""))
};

How can I deal with it in ClojureScript?

Again, note the dependency of fullName on this and firstName/lastName.

Upvotes: 2

Views: 246

Answers (2)

dnolen
dnolen

Reputation: 18556

Riffing on @Ankur's answer, seems like you could also do the following:

  (deftype AppViewModel [firstName lastName fullName])

  (defn my-model [first last]
    (AppViewModel. 
      (.observable js/ko "Bob") 
      (.observable js/ko "Smith")
      (.computed js/ko (str (firstName) " " (lastName)))))

Upvotes: 1

Ankur
Ankur

Reputation: 33637

Try this:

(defn my-model [first last]
  (let [fname (.observable js/ko first)
        lname (.observable js/ko last)
        full-name (.computed js/ko #(str (fname) " " (lname)))] 
        (js-obj "firstName" fname
                "lastName" lname
                "fullName" full-name)))

Upvotes: 3

Related Questions