Why does updating my nested Reagent component not update it? - clojurescript

I have a triply nested component (in different files) in Reagent + ShadowCLJS. When editing and saving this file, the changes don't show immediately until editing and saving the parent component.
For example, NAV is nested in DASHBOARD which itself is nested in APP. Editing and saving DASHBOARD result in changes also in the browser, but editing and saving NAV does not, until DASHBOARD itself is modified, then NAV will show changes in the browser.
Example code:
(ns app.core
(:require [app.views.dashboard :as dash]))
(defn app[]
[dashboard])
(ns app.views.dashboard
(:require [app.components.nav :as nav]))
(defn dashboard[]
[:div
[:div "Dashboard"]
[nav/nav]])
(ns app.components.nav)
(defn nav[]
[:div "Navigation"])
Build configuration:
;;shadow-cljs.edn
...
{:app {:target :browser
:modules {:main {:entries [app.core]}}}
...
I tried un-nesting the namespaces so that the components live next to each other in the directory, but still triply nested. This also does not work.

I wrote about hot-reload in CLJS, maybe you can find an answer there.
Normally I'd expect your setup to just work, but I suspect that reagent/react decides to skip rendering at some point. They memoize some components and since CORE doesn't change, when touching NAV it may decide that nothing needs to be done.
You can force a full reload by setting :devtool {:reload-strategy :full} in your build config, which should address this problem. It may however become somewhat slow in larger builds.

After 5 hours of meddling around, it turns out if C is nested in B which is nested in A (A (B (C))), not only do you have to import C inside B, but you also have to import it inside A. So my solution was to also :require app.components.nav inside app.core.
I'm not very sure why this behaves like this, so if anyone else would like to respond with an explanation, that would be welcome!

Related

PhpStorm - Choose which SASS-files to show autocomplete from first

I'm working on a project that has:
Bootstrap
FontAwesome
It's own custom stylings
When I write something like this:
.some-el {
font-size: $f (and then wait)
}
Then it thinks for a second and then suggests something like this:
$focus [my variable]
$fa-font-display [implicitly imported from font-awesome]
$fa-font-path [implicitly imported from font-awesome]
$fa-css-prefix [implicitly imported from font-awesome]
$font_size_base [my variable - that I was looking for]
...
...
It gets better with time, since it remembers what I've used previously - so I guess this is something that would fix itself. But it would be awesome to be able to fix it myself right away.
This is just an example where FontAwesome-variable are a nuisance, but other times it's the Bootstrap-variables.
How can I define which SASS-variables that are suggested (and/or the order of the suggestions)?
Solution attempts
Googled a bunch.
Looking through settings for 'Code Completion' and 'Code Style'
It's not possible. The only way I can think of is excluding the folder where the .css/.scss files you don't like getting completion from are stored from indexing (Mark directory as/excluded).
Related feature request: WEB-41257

Serializing ClojureScript edn as a text file (like json)?

I am working in ClojureScript and would like to serialize a massive EDN data structure (in particular: a large map) in the form of a text file (in the same way that JS objects are stored as .json files). Performance concerns are not an issue.
Is this possible, and if so, is there considered a standard/best practice way to do this?
Yes.
Use pr-str or clojure.pprint/pprint to write EDN and use clojure.edn/read-string to ingest EDN.
In ClojureScript you may face the same challenges as Javascript in accessing the filesystem from a browser. For example to save a file from the browser things can be a little tricky:
(defn save-file [filename t s]
(if js/Blob
(let [b (js/Blob. #js [s] #js {:type t})]
(if js/window.navigator.msSaveBlob
(js/window.navigator.msSaveBlob b filename)
(let [link (js/document.createElement "a")]
(aset link "download" filename)
(if js/window.webkitURL
(aset link "href" (js/window.webkitURL.createObjectURL b))
(do
(aset link "href" (js/window.URL.createObjectURL b))
(aset link "onclick" (fn destroy-clicked [e]
(.removeChild (.-body js/document) (.-target e))))
(aset link "style" "display" "none")
(.appendChild (.-body js/document) link)))
(.click link))))
(log/error "Browser does not support Blob")))
So it depends on the context of how you access the files, but so long as you can get/put strings, it's as easy as pr-str and edn/read-string.
It is very possible.
This approach gives you a url string such as "blob:http://localhost:3000/4a6407c6-414e-4262-a194-28bd2b72be00", where your data will be available for download on a browser.
(defn download-as-edn [coll]
(-> coll
str
vector
clj->js
(js/Blob. #js {:type "text/edn"}))
js/URL.createObjectURL))
Notice that Blob takes a sequence, therefore we pass it the edn string inside a vector.

How can I add a new category to a morea site?

I'm trying to add a new 'project' category to a morea based site, where there will be a page similar to experiences page where I'll collect all course project related experiences and assignments, and maybe even modules.
Is it ok to look for pages with 'project' in their id or maybe better to tag with a new morea tag?
Do I need to also create a new entity type called 'project' or just reuse existing entities
In MoreaGeneraor.rb I couldn't find where module level page collections are prepared, like for example module_page.data['morea_experiences'].
I thought of preparing a similar collection of 'morea_project' pages and then traversing it in the new project page.
Is that done outside of this .rb file? by Jekyll? so how do I inject my collection.
Any simpler idea?...
Thank
p.s. I've also added the following (from line 3) to 'processMoreaFile()', but it does not seem to be visible at later stages:
elsif new_page.data['morea_type'] == "assessment"
site.config['morea_assessment_pages'] << new_page
if new_page.data['morea_id'].include?('project')
site.config['morea_project_pages'] << new_page
puts "--- project page #{new_page.data['morea_id']}\n "
end
but still do not know where to let each module page find out about it's 'project' pages
This is a cool idea. The simplest approach is to avoid making changes to MoreaGenerator.rb, and instead do it using normal Jekyll mechanisms. Here's a sketch:
Add a morea_label called "Project" to each associated module, reading, experience, and assessment.
In master/src, create a new directory called project, containing a file called index.md. This adds a new top-level page to your site (i.e. http://example.com/ics101/project/index.html)
Implement the index.md file with liquid tags to create the desired page layout for your project page. For inspiration, see the index.md files in the other top-level pages (readings, experiences, etc.). You can access YAML content in Liquid.
Once you've got your rocking project page done, you'll want a link to it in the navbar. See add a menu item for instructions.
Good luck! If you get it working to your satisfaction, please post its link as a followup to this question so we can see how it turned out!

Django code to open sepecific tab in render_to_response in view

In my Django code I want to implement the following flow:
After submitting a Html form to view
Redirect to next tab in same HTML form which contain next form.
This is my code so far:
def addnewroute(request):
if request.method == "POST":
# do needed
render_to_response('useradd.html')
Introduction
Tabs are usually a visual (UI) element; meaning that there are CSS styles defining the actual tabs as "pressed" or "depressed". How the tabs "change" is defined by the implementation method you choose. Let's look at the simplest solutions.
Manual render (hard code / multi template)
If you prefer to build it all manually, you can add a condition to choose the correct html template, which would already be pre-styled to the correct tab pressed, and display the required content. I would not recommend this method except to learn more of how the internals work and as proof of concept.
def addnewroute(request):
# ...
if step1:
return render_to_response('useradd-tab1.html')
if step2:
return render_to_response('useradd-tab2.html')
Context / Template reuse
If you prefer to reuse most of your template content you can utilize the context dictionary argument to pass a step variable (to define in "which tab you should be now"), and a content variable (containing the tab content or other switch data), into your template; which will change depending on the reached step:
def addnewroute(request):
# ...
if step1:
return render_to_response('useradd.html', {'step': 1, 'form': form1})
if step2:
return render_to_response('useradd.html', {'step': 2, 'form': form2})
Then, use the passed context variables in your template, to define the condition that toggles the selected style on the tabs and displays the relevant form.
<div id="tab1" class="tab{% if step1 %} selected{% endif %}">...</div>
{{ form.as_table }}
This method is very similar to the first, except the same template is reused for both steps.
Caveats with above direct render implementations
The above methods can accomplish what you asked about; however, there are a few caveats. First, the URL remains the same, which means the user cannot navigate between steps in a persistent manner. Second, the amount of "wiring code" you would have to write (front and back-end) will be a real labor. This is why I would recommend one of the following implementations for a "stepped form".
Form Wizard
Django (versions >= 1.4, < 1.8) shipped with an "optional “form wizard” application that splits forms across multiple Web pages". The Django Form Wizard uses a specialzed WizardView class based view to simplify multi-step form creation. Note: As of Django 1.8, The form wizard was moved out of django.contrib into it's own package django-formtools.
Javascript
A more sophisticated solution may involve Javascript activated tabs, such as bootstrap tabs. In this case you would have to either: a. render all the forms in the same template (hidden by default, toggleable by on-click events) or b. fetch the data for the forms asynchronously. The upside of this solution is a more immediate UI feel for the user, the downside is definitely more complexity.
More help
If you are new to Django, templates, tabs, etc, I would suggest implementing the solutions above from the first to the last, to better understand how the internals work; and then, how you can DRY and simplify your code.
Please note that similar questions has been asked a few times on SO, such as here, here and here. So if you have any more trouble you can try searching for a related answer.

Emacs jump to css declaration from html file

I have been looking around the internets and have not come up with a solution. Does anyone know how to jump to a css declaration inside an html file and have a new buffer open with point at or close to that declaration?
Edit
After more searching I decided to go with a search open buffers for string approach.
;; CSS search open buffers
(defun search-open-css-buffers-for-region-or-word ()
"Use the current region/point and search open css buffers"
(interactive)
(let (searchTerm)
(setq searchTerm
(if (region-active-p)
(buffer-substring-no-properties (region-beginning) (region-end))
(thing-at-point 'symbol)))
(multi-occur (mapcar (lambda (buf)
(if (string-match "\w*.css" (buffer-name buf))
buf)) (buffer-list))
searchTerm 5)))
(global-set-key (kbd "M-s-.") 'search-open-css-buffers-for-region-or-word)
It feels like this is a hack though.
There's a couple of things that make this non-generic:
depending on what HTML mode you use you might need different ways of detecting what is at point
where are your CSS files? people have all sorts of different project structures
how do you want the output to look?
Having said that, here's an example, for nxml-mode (though it could easily be adapted).
(defun find-css-defun ()
(interactive)
(when (memq 'nxml-attribute-value
(get-text-property (point) 'face))
(let ((css-buffers
(mapcar
(lambda (file)
(find-file-noselect file))
(directory-files default-directory t ".*\\.css$"))))
(multi-occur css-buffers
(thing-at-point 'symbol)))))
answer to first point, we're using nxml so that's how we detect whether we're on a CSS attribute or not
answer to second point, we just scan through all CSS files in the same directory as the HTML, css-buffers is a list of opened CSS files; clearly this is adaptable
we use multi-occur to present the results
It works ok.
PS it requires thing-at-point which is in emacs by default these days