Search code examples
metadatametaprogrammingclojurescripttemplate-meta-programming

How to pass the variable name as a string to a function? (ClojureScript)


Description of the situation

I want to make a form template for an element, but they must be dynamically created. The meta data involved in the Component should use the variable-name passed as it's meta-data.

Code

For example,

In the view,

(ns my.app
  (:require [my.app.templating :as template])

(defn view-component [nOperacaoExtrato]
    [:<>
      (template/temp-form nOperacaoExtrato)])

The templating function,

(ns my.app.templating)

(defn temp-form
  "Template input"
  [dado]
  #_(js/console.log (str "meta-data: " (meta #'dado)))
  (let [nome-var (:name (meta #'dado))]
    [:div.col
     [:label
      {:for (str "form1_" nome-var)}
      "Natureza do Dispendio"]
     [:p
      {:class "form-control",
       :id (str "form1_" nome-var)
       :name (str "form1" nome-var)}
       dado]]))

The result should be, something like this (because the variable passed is nOperacaoExtrato):

       [:div.col
        [:label
         {:for "form1_re-fin-n-operacao-extrato-prop"}
            "Nº da Operação no Extrato"]
          [:p
         {:class "form-control",
          :id "form1_re-fin-n-operacao-extrato-prop",
          :name "form1_re-fin-n-operacao-extrato-prop"}
         (h/preencher-str nOperacaoExtrato)]]

The issue:

Both of these return null.

(meta #'data)
(meta data)
``

Solution

  • You should probably convert this function to a macro. Let me show you fellow Portuguese speaker:

    src/cljs/user.cljc

    (ns cljs.user)
    
    (defn temp-form-fn
      "Template input"
      [dado nome-var]
      [:div.col
       [:label
        {:for (str "form1_" nome-var)}
        "Natureza do Dispendio"]
       [:p
        {:class "form-control",
         :id (str "form1_" nome-var)
         :name (str "form1" nome-var)}
        dado]])
    
    #?
    (:clj
     (defmacro temp-form
       [dado]
       `(temp-form-fn ~dado ~(name dado))))
    

    Then in the repl:

    cljs.user> (require '[cljs.user :refer-macros [temp-form]])
    nil
    cljs.user> (let [nOperacaoExtrato 1234]
                 (temp-form nOperacaoExtrato))
    [:div.col
     [:label {:for "form1_nOperacaoExtrato"} "Natureza do Dispendio"]
     [:p
      {:class "form-control",
       :id "form1_nOperacaoExtrato",
       :name "form1nOperacaoExtrato"}
      1234]]