ClojureScript no such namespace - clojure

I am new to Clojure and I am trying to implement some ClojureScript functions in my project. I added [org.clojure/clojurescript "0.0-2138"] to my dependencies in project.clj. I tried for example:
(js/alert "Hello from ClojureScript.")
It says No such namespace: js!
What am I doing wrong? Can anyone help?
Here is my complete project.clj:
(defproject MyProject "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"][table "0.4.0"][cljs-uuid "0.0.4"][lein-swank "1.4.5"][midje "1.5.1"]
[mysql/mysql-connector-java "5.1.18"][org.clojure/java.jdbc "0.1.1"]
[ring/ring-jetty-adapter "1.1.6"]
[compojure "1.1.3"]
[hiccup "1.0.2"]
[org.clojure/clojurescript "0.0-2138"]
[domina "1.0.2"]
[prismatic/dommy "0.1.1"]]
:plugins [[lein-cljsbuild "0.3.4"]]
;; cljsbuild options configuration
:cljsbuild {:builds
[{;; CLJS source code path
:source-paths ["src/cljs"]
;; Google Closure (CLS) options configuration
:compiler {;; CLS generated JS script filename
:output-to "resources/public/js/test.js"
;; minimal JS optimization directive
:optimizations :whitespace
;; generated JS code prettyfication
:pretty-print true}}]}
)
This is the file where I am trying to put the ClojureScript function. I am using Eclipse and Clojure REPL.
(ns webapp.pages
(:use [compojure.core :only (defroutes GET)]
[ring.adapter.jetty :as ring])
(:require [clojure.java.jdbc :as sql])
(:require
[ring.util.response :as resp])
(:use [hiccup.page :only (html5 include-css include-js)])
(:use webapp.db)
)
(defn showAlert []
(js/alert "Hello from ClojureScript.")
)
(defn insert-user [firstname lastname email password sex date]
(sql/with-connection db
(sql/insert-values :users
[:name :lastName :email :password :birthDate :gender]
[firstname lastname email password date sex])
)
(resp/redirect "/")
(showAlert)
)
(defn index []
(html5
[:head
[:title "Kladionica"]
[:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]
(include-css "/public/css/bootstrap.min.css")
]
[:body
[:div {:class "modal fade" :id "myModal" :role "dialog" :aria-hidden "true"}
[:div {:class "modal-dialog"}
[:div {:class "modal-content"}
[:div {:class "modal-header"}
[:button {:type "button" :class "close" :data-dismiss "modal"}"x"]
[:h3 "Registracija"]
]
[:div {:class "modal-body"}
[:form {:action "/insert-user" :method "post" :class "form" :role "form"}
[:div {:class "row"}
[:div {:class "col-xs-6 col-md-6"}
[:input {:class "form-control" :style "margin-bottom: 10px;" :name "firstname" :placeholder "Ime" :type "text"}]
]
[:div {:class "col-xs-6 col-md-6"}
[:input {:class "form-control" :style "margin-bottom: 10px;" :name "lastname" :placeholder "Prezime" :type "text"}]
]
]
[:input {:class "form-control" :style "margin-bottom: 10px;" :name "email" :placeholder "Email" :type "email"}]
[:input {:class "form-control" :style "margin-bottom: 10px;" :name "password" :placeholder "Lozinka" :type "password"}]
[:input {:class "form-control" :style "margin-bottom: 10px;" :name "re-password" :placeholder "Ponovljena lozinka" :type "password"}]
[:label {:for ""} "Datum rodjenja"]
[:div {:class "row"}
[:div {:class "col-xs-4 col-md-4"}
[:select {:class "form-control" :name "month"}
[:option {:value "" :disabled "disabled" :selected "selected"} "Mjesec"]
[:option {:value "01"} "Januar"]
[:option {:value "02"} "Februar"]
[:option {:value "03"} "Mart"]
[:option {:value "04"} "April"]
[:option {:value "05"} "Maj"]
[:option {:value "06"} "Jun"]
[:option {:value "07"} "Jul"]
[:option {:value "08"} "Avgust"]
[:option {:value "09"} "Septembar"]
[:option {:value "10"} "Oktobar"]
[:option {:value "11"} "Novembar"]
[:option {:value "12"} "Decembar"]
]
]
[:div {:class "col-xs-4 col-md-4"}
[:select {:class "form-control" :name "day"}
[:option {:value "Day" :disabled "disabled" :selected "selected"} "Dan"]
(for [i (range 1 32)]
[:option {:value i} i]
(inc i))
]
]
[:div {:class "col-xs-4 col-md-4"}
[:select {:class "form-control" :name "year"}
[:option {:value "Year"} "Godina"]
(for [i (range 1900 2015)]
[:option {:value i} i]
(inc i))
]
]
]
[:label {:class "radio-inline"}
[:input {:type "radio" :name "sex" :id "maleId" :value "male"}]
"Musko"
]
[:label {:class "radio-inline"}
[:input {:type "radio" :name "sex" :id "femaleId" :value "female"}]
"Zensko"
]
[:br]
[:br]
[:button {:class "btn btn-lg btn-primary btn-block" :type "submit"} "Registruj se"]
]
]
[:div {:class "modal-footer"}
]
]
]
]
[:div {:class "navbar navbar-inverse navbar-static-top"}
[:div {:class "container"}
[:a {:href "#" :class "navbar-brand"} "TOP Kladionica"]
[:div {:class "navbar-collapse collapse"}
[:ul {:class "nav navbar-nav navbar-right"}
[:li [:a {:href "#myModal" :data-toggle "modal"} "Registracija"]]
[:li {:class "dropdown"}
[:a {:href "#" :class "dropdown-toggle" :data-toggle "dropdown" } "Login" [:b {:class "caret"}]]
[:ul {:class "dropdown-menu" :style "padding:15px;min-width:250px;"}
[:li
[:div{:class "row"}
[:div {:class "col-md-12"}
[:form {:class "form" :role "form" :method "post" :action "login" :accept-charset "UTF-8" :id "login-nav"}
[:div {:class "form-group"}
[:label {:class "sr-only" :for "inputEmail"} "Email adresa"]
[:input {:type "email" :class "form-control" :id "inputEmail" :placeholder "Email adresa" }]
]
[:div {:class "form-group"}
[:label {:class "sr-only" :for "inputPassword"} "Lozinka"]
[:input {:type "password" :class "form-control" :id "inputPassword" :placeholder "Lozinka" }]
]
[:div {:class "checkbox"}
[:label
[:input {:type "checkbox"} "Zapamti me"]
]
]
[:div {:class "form-group"}
[:button {:type "submit" :class "btn btn-success btn-block"} "Login"]
]
]
]
]
]
[:li {:class "divider"}]
[:li
[:input {:class "btn btn-primary btn-block" :type "button" :id "sign-in-google" :value "Google prijava"}]
[:input {:class "btn btn-primary btn-block" :type "button" :id "sign-in-twitter" :value "Twitter prijava"}]
]
]
]
]
]
]
]
[:div {:class "navbar navbar-default navbar-fixed-bottom"}
[:div {:class "alert alert-success alert-dismissable pull-right" :style "display:none"}
[:button {:type "button" :class "close" :data-dismiss "alert" :aria-hidden "true"} "x"]
[:strong "Uspijeh!"] "Uspjesno ste se registrovali!"
]
]
(include-js "//code.jquery.com/jquery-1.10.2.min.js")
(include-js "/public/js/bootstrap.js")
]
)
)

A couple of things here.
First of all, ClojureScript is a separate (but related) language with its own compiler, so you can't just put ClojureScript code in a Clojure file.
Second, ClojureScript needs to be compiled into JavaScript in order to do anything, and then that JavaScript needs to be executed by a JavaScript engine. You can do the compiling with the lein-cljsbuild plugin.
For a quick and easy introduction to ClojureScript, take a look at David Nolen's The Essence of ClojureScript. It will get you up and running in literally seconds, and you can take a look around the generated project.clj file to see how a project can be set up for ClojureScript if you're curious.
However, if you're very new to Clojure, it might be better to get comfortable with Clojure and Leiningen before jumping into ClojureScript. You don't have to, but it might be easier.

As other users are commenting here, you have to separate ClojureScript code from Clojure code (if you use cljsbuild to build cljs code the standard way is separate directories).
Why don't you use Clojure and ClojureScript in the same file?
This is not the exact question, as you should feel the ClojureScript code as Clojure code when typing it. The problem is that when you try to use an external Clojure library (not the core Clojure) in your ClojureScript code, then such external library uses the host JVM classes, while the ClojureScript one uses the host Javascript classes. That's the reason you have to use ClojureScript libraries (libraries adapted to JavaScript classes) inside ClojureScript code, and that's the reason your file is a bit messy.

Related

OM how to add class to html element

Trying out OM, ReactJS and ClojureScript. I am trying to add a classname to my dom element. Ideally I want something like this:
<div>
<i class="icon-alert">Contact list</i>
</div>
right now: It writes like:
<div>
<i>Contact list</i>
</div>
This is my core.clj
(defn new-view [data owner]
(reify
om/IRender
(render [this]
(dom/i #js {:class "icon-alert"} "Contacts list")
)))
(om/root new-view app-state
{:target (. js/document (getElementById "row1"))})
This is the relevant part from my index.html
<div id="row1">
<h2>Figwheel template</h2>
<p>Checkout your developer console.</p>
</div>
Any ideas of what I am doing wrong?
Playing around with my code, make me realise: I was writing class instead of className. Feel so dumb. It works now. I will let it here so people with the same issues can get the help they need.
(defn new-view [data owner]
(reify
om/IRender
(render [this]
(dom/i #js {:className "icon-alert"} "Contacts list")
)))

ActiveAdmin Nested Form multiple select

I'm trying to get the product_suppliers to update via the product form. The form displays all suppliers in the supplier table but it doesn't update the join table. Not sure where the error lies. Index and show show correct details but edit is not updating the join table. Starting to go around and around in circles on this one.
Update: Changing the form to the below has got me close. But still not updating the join table. However delete works as expected if i manually add rows to the join table. They display and can be deleted. Saving adds new product_id into the row just not the associated supply_company_id value. I figure its an attribute issue but i cant see it.
app/models/product.rb
class Product < ActiveRecord::Base
### shortned for clarity
has_many :product_suppliers, :foreign_key => 'product_id'
has_many :supply_companies, :through => :product_suppliers
accepts_nested_attributes_for :product_suppliers, :allow_destroy => true
end
app/models/supply_company.rb
class SupplyCompany < ActiveRecord::Base
has_many :products, :through => :product_suppliers
has_many :product_suppliers, :foreign_key => 'supply_company_id'
end
app/models/product_supplier.rb
class ProductSupplier < ActiveRecord::Base
belongs_to :product
belongs_to :supply_company
accepts_nested_attributes_for :product
accepts_nested_attributes_for :supply_company
end
/app/admin/product.rb
ActiveAdmin.register Product do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
permit_params :id, :product_name, :product_description, :product_type_id, :product_category_id, :product_colour_id, :product_size_id,
product_images_attributes: [:id, :product_id, :product_image, :_destroy],
product_types_attributes: [:id, :product_type],
product_catergories_attributes: [:id, :product_category],
product_colour_attributes: [:id, :product_colour],
product_size_attributes: [:id, :product_size],
product_suppliers_attributes: [:id, :product_id, :supply_company_id, :_destroy],
supply_companies_attributes: [:id, :company_name]
form(:html => {:multipart => true}) do |f|
f.inputs "Product Details" do
f.input :id
f.input :product_name
f.input :product_description
#######################################################################
# Problem Lies with this piece of code Not saving the supply_company_id
# when adding a new row or updating the old rows. Delete works fine.
# cant see the error in models or permited_params.......
#######################################################################
f.inputs "Suppliers" do
f.has_many :product_suppliers do |ff|
ff.input :supply_company_id, as: :select, multiple: true, collection: SupplyCompany.all.map {|u| [u.company_name.to_s, u.id]}
ff.input :_destroy, :as=>:boolean, :required => false, :label => 'Remove supplier'
end
end
########################################################
f.input :product_type_id, :as => :select, :collection => ProductType.all.map {|u| [u.product_type.to_s, u.id]}
f.input :product_category_id, :as => :select, :collection => ProductCategory.all.map {|u| [u.product_category.to_s, u.id]}
f.input :product_colour_id, :as => :select, :collection => ProductColour.all.map {|u| [u.product_colour.to_s, u.id]}
f.input :product_size_id, :as => :select, :collection => ProductSize.all.map {|u| [u.product_size.to_s, u.id]}
end
f.inputs "Product images" do
f.has_many :product_images do |p|
p.input :product_image, :as => :file, :label => "Image",:hint => image_tag(p.object.product_image.url(:thumb))
p.input :_destroy, :as=>:boolean, :required => false, :label => 'Remove image'
end
end
f.actions
end
product_suppliers_schema
create_table "product_suppliers", force: true do |t|
t.integer "product_id"
t.integer "supply_company_id"
t.datetime "created_at"
t.datetime "updated_at"
end
Update:
Changing the form to the below has got me close. But still not updating the join table. However delete works as expected if i manually add rows to the join table. They display and can be deleted.
Saving adds new product_id into the row just not the associated supply_company_id value. I figure its an attribute issue but i cant see it.
f.inputs "Suppliers" do
f.has_many :product_suppliers do |ff|
ff.input :supply_company_id, as: :select, multiple: true, collection: SupplyCompany.all.map {|u| [u.company_name.to_s, u.id]}
ff.input :_destroy, :as=>:boolean, :required => false, :label => 'Remove supplier'
end
end
Turns out it was the multipart: :true in the code. Once I removed it from the below code everything worked as expected.
form(:html => {:multipart => true}) do |f|
f.inputs "Product Details" do
f.input :id
f.input :product_name
f.input :product_description
f.has_many :product_supply_companies do |ff|
###############################################
#REMOVED multipart: :true from the line below
###############################################
ff.input :supply_company_id, as: :select, collection: SupplyCompany.all.map {|u| [u.company_name.to_s, u.id]}
ff.input :_destroy, :as=>:boolean, :required => false, :label => 'Remove supplier'
end
f.input :product_type_id, :as => :select, :collection => ProductType.all.map {|u| [u.product_type.to_s, u.id]}
f.input :product_category_id, :as => :select, :collection => ProductCategory.all.map {|u| [u.product_category.to_s, u.id]}
f.input :product_colour_id, :as => :select, :collection => ProductColour.all.map {|u| [u.product_colour.to_s, u.id]}
f.input :product_size_id, :as => :select, :collection => ProductSize.all.map {|u| [u.product_size.to_s, u.id]}
end
f.inputs "Product images" do
f.has_many :product_images do |p|
p.input :product_image, :as => :file, :label => "Image",:hint => image_tag(p.object.product_image.url(:thumb))
p.input :_destroy, :as=>:boolean, :required => false, :label => 'Remove image'
end
end
f.actions
end

ClojureScript/Om: Rendered HTML is missing attributes

I have a dead simple ClojureScript/Om application. It seems a little broken.
This is the core file:
(ns demo.core
(:require-macros [cljs.core.async.macros :refer [go]])
(:require [goog.events :as events]
[cljs.core.async :as async :refer [>! <! put! chan]]
[om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[goog.events.EventType :as EventType]
[clojure.string :as string]))
(defn layout
[app owner]
(reify
om/IRender
(render [_]
(dom/div {:id "some-id"} "Pumpkin"))))
(defn main []
(om/root
layout
{}
{:target (. js/document (getElementById "app"))}))
It renders this HTML:
<div id="app">
<div data-reactid=".0">Pumpkin</div>
</div>
Why doesn't the div have the id #some-id?
You need to use the #js {} reader literal to specify a JS object rather than a plain-old map:
(dom/div #js {:id "some-id"} "Pumpkin")
This is elaborated a bit in the Om Tutorial.

Form Helper not found when using select_recurring for Ice_Cube with Formtastic and ActiveAdmin.

When using the select_recurring form helper for the Ice_Cube gem in Formtastic with ActiveAdmin I receive a unable to find input class for select_recurring error.
form do |f|
#Debugging
f.semantic_errors *f.object.errors.keys
f.inputs do
f.input :title
f.input :description, :hint => "Full description for the event"
f.input :short_description, :hint => "Shot description for the event that will be displayed as a thumbnail"
f.input :published
f.input :event_date
f.input :recurring_rule, :as => :select_recurring
end
f.actions
end
Accessing it directly (below) works for the recurring schedule element but breaks all of the rest of the formtastic f.input elements.
f.select_recurring :recurring_schedule
How can I incorporate select_recurring into ActiveAdmin?
worked for me (AA 1.0.0.pre1)
form do |f|
f.inputs do
#...
li do
f.label :recurring_rule_column
f.select_recurring :recurring_rule_column, nil, :allow_blank => true
end
#...
end
f.submit
end

How to generate a list of a pair of elements in Enlive?

I'm new to Enlive. I found that I can iterate with clone-for, however, it works for single element. I want to generate a list of a pair of elements like the following:
<div>
item 1<br>
item 2<br>
...
</div>
I tried to select <a> and use clone-for, but end with following result:
<div>
item 1item 2......<br>
</div>
What do I do to repeat <a> with <br> in each iteration?
I think fragments will work in this case.
Try something along these lines:
(html/sniptest "<div>Label<br/></div>" {[:a] [:br]}
(clone-for [{label :label url :url} [{:label "Google" :url "http://www.google.com" }
{:label "Stack Overflow" :url "http://www.stackoverflow.com"}]]
[:a] (do-> (content label)
(set-attr :href url)))))
;; =>
<div>
Google<br />
Stack Overflow<br />
</div>
If you always want the full content of the div to be cloned (not just the fragment :a -> :br) then you can use first-child and last-child. Just change the {[:a] [:br]} selector above to {[:div first-child] [:div last-child]}.