This is a read-only archive of the Framer Community on Facebook.

What is Framer? Join the Community
Return to index
Logan Merriam
Posted Jun 02 - Read on Facebook

If I create a layer in a function, then call the function, then try to reference the layer in the code (say, calling an event on it) it can't find the layer: ReferenceError: can't find variable: layerName

I can see the layer, but javascript can't. Why is that?


Logan Merriam

Ah okay, looks it's because the variable gets created in the scope of the function and isn't available outside of it. If I declare the variables, then call the function, then target the layer it works. Is there a way around this though? Say I want to put this thing into a module, I don't want to be required to manually declare all these variables in every project I use the module in.

Joshua Tucker

Logan Merriam Hey there! You are correct on scope. Here's a few different things you could do.

If you're creating one layer in your function, you could say set a variable to the function and return the layer inside the function. As commented, Coffeescript returns the last expression unless specified, so if you're creating the layer last, you're solid. Otherwise make sure to return the variable name of the created layer explicitly.

Second, creating a layer using window["[layerName]]" puts the layer back into global scope, allowing you to reference the layer by name. I gave an example of say creating a number of different layers inside said function and adding them to the global scope. Note that it would be a good idea to house an array of names so that you can set the name property on each layer. Otherwise they show up as "window" in the layer inspector.

It sounds like you'll be creating the layer(s) inside your module/function. I'd recommend using the window[["layerName"]] method and have all the variable names (string names) on the module side so you can create the variables over there. Once it's done over there, they are able to be referenced on the project side without having to explicitly declare variables on the Framer Studio side.


Logan Merriam

What an awesome response!

Logan Merriam

I'm a little confused about one part: what's the deal with the createLayer() function and the layerName = createLayer() call?

Joshua Tucker

Logan Merriam No worries! That first part with the createLayer function was to demonstrate how you could return the reference of the layer (local scope) and capture it on the outside of the function (higher scope), by declaring it on the Framer Studio end. Just one example of getting a reference for a variable inside a function on the outside.

I wrote this below at first before I re-processed your question thinking that it may have been confusing just simply because I had two examples there. Nonetheless, my edit will include this just in case:


So, every function has a return. The return tells the function to stop and return back to where you were and continue the code. Coffeescript automatically returns the last expression without having to specify a return (which is traditional JavaScript).

In the case of layerName = createLayer(), inside the function, I created a new layer named layer. Like you mentioned, it's in local scope. To get a reference to that layer, I am returning layer (not an explicit "return layer" because Coffeescript does it for me) and layerName is now has a reference to that layer you created.

Now, Framer populates the layer list using the original variable name, unless a name property is specified. That's why you see it as "layer" in the list, and not "layerName." layerName is merely a variable that is referencing the layer I created. However, if you were to set the name property to "layerName" (or whatever you wanted), say by passing it into the function, then it would be named accordingly in the list and your variable name would be the same too.


Logan Merriam

Joshua Tucker OH your screenshot shows both examples! Thought it was just the second

Joshua Tucker

Logan Merriam It's all good. I debated just sharing the project so you could download it, but I'm always hesitant to share really, really small files. Seems like a waste. Maybe I'm doing it the stupid way :P. Does that all make sense though? Off to build this cool module now, right? We'll be excited to see it!

Jordan Robert Dobson

^ I think it's good to ask people to "translate" it and hopefully get a closer connection to what they are building.

Logan Merriam

Yep this is great, I'm all unblocked. Thanks!

Logan Merriam

Joshua Tucker ran into another question: I've got an element (submit button) that needs to trigger a state change on the elements generated by my function (form inputs). Can't figure out a clever way to iterate over the generated elements.

Logan Merriam

huh, I wonder why this doesn't work:

Logan Merriam

nevermind... that was a very basic mistake :)

Aaron James

Wow Joshua Tucker! Your example really helped me out. Thanks for posting your example. Really appreciate it!

Elias Suske

Joshua Tucker this is awesome, suddenly everything works :)

My function within my module is now following:

exports.myLayerCreator = (nameR, color) ->
window["#{nameR}"] = new Layer
x: 100
y: 100
width: 200
height: 200
borderRadius: 8
backgroundColor: color
name: "#{nameR}"

Can u explain me, how this "window" works and why its this "#{name}" syntax? Or do you have a reference link for me?

Read the entire post on Facebook