Closed chopfitzroy closed 4 years ago
Hi @CrashyBang - there's not a components API currently but there is a similar concept on the roadmap for v3.
Obviously the reason there isn't any templating with JSX or render function is because Alpine is designed to live in the plain DOM. Feel free to make a PR with some links if you think other people would find it useful, or alternatively, make a PR on the alpinejs/awesome-alpine repo with some links too (I think this one might be better).
Hey @ryangjchandler,
Makes total sense, will do thank you! Also is there a spec/RFC? for the proposed v3 api?
Cheers, Otis.
Hey @ryangjchandler,
Makes total sense, will do thank you! Also is there a spec/RFC? for the proposed v3 api?
Cheers, Otis.
There's no spec or RFC yet, that's a good idea though. I'll be sure to bring it up with the rest of the team.
@ryangjchandler Assuming you're rending on the server (e.g., Rails, Django, Laravel), why do you need components? In Django, I think you can just create a file called MyShinyAlpineComponent.html
. Then in your main template file, you use pass "props" to the component like so:
{% include "MyShinyAlpineComponent.html" with prop1="Hello" prop2="World" only %}
@pandichef The proposed component API for Alpine won't be used for templating / markup since that isn't what Alpine was designed for, and as you mentioned, this can all be done on the server.
Instead, it will provide a standardised way of defining re-usable component functions with support for initialiser methods without needing to define x-init
and potentially some more developer-experience focused improvements.
@ryangjchandler Actually, I take back what I said. Imagine you have this in your Django base.html
template:
{% include "MyShinyAlpineComponent.html" with prop1="Hello" prop2="World" only %}
Django will just copy/paste the contents of MyShinyAlpineComponent.html
into the top-level template.
Now say base.html
and MyShinyAlpineComponent.html
BOTH have Alpine.js components. Then the include
statement above will create a nested component, which I believe isn't supported.
Do you see what I mean? Is there currently a solution/workaround for this?
(I realize not everyone here is familiar with Django, but I'm sure Rails/Laravel users would face the same issue.)
You can have nested components in Alpine, that's fine. Those components can't access parent data though.
Can we have an issue to subscribe to be informed about components progress? Reusing same template in different parts of the page is crucial sometimes. Thanks!
@dector as I said above, the proposed x-component
directive will NOT have anything to do with templating or the markup for your component. Instead it will provide a way of writing more immediately reusable data sets & functions, whilst reducing the amount of directives you need to define in your markup.
If you need re-usable templates, I would consider using a server-side template engine or a more monolithic front end framework such as Vue or React.
Well, yeah. All these options that you described definitely works. It's a bit sad that alpine don't have built-in mechanism for achieving this functionality. Thanks.
@dector - the functionality you are looking for is far out of the scope of Alpine. It's designed to work alongside your existing markup from the server or static files, not replace / component-ise your markup.
@ryangjchandler
You can have nested components in Alpine, that's fine. Those components can't access parent data though.
Is this what you mean?
<div x-data='{parent: "I am in the parent", shared: "I am also in the parent"}'>
<div x-text="parent"></div> <!-- This works -->
<div x-text="shared"></div> <!-- This works -->
<div x-text="child"></div> <!-- Uncaught ReferenceError: child is not defined -->
<!---------------------------------------------------------------->
<!-- Alpine "component" inserted by server side template engine -->
<div x-data='{child: "I am in the child", shared: "I am also in the child"}'>
<div x-text="parent"></div> <!-- Displays "[object Window]" in the browser -->
<div x-text="shared"></div> <!-- This works -->
<div x-text="child"></div> <!-- This works -->
<div x-text="blah"></div> <!-- Uncaught ReferenceError: blah is not defined -->
</div>
<!---------------------------------------------------------------->
</div>
In the browser you get:
I am in the parent
I am also in the parent
[object Window]
I am also in the child
I am in the child
It seems like the child is aware of the parent
variable's existence, but it displays [object Window]
instead of null or throwing an error. Is this the behavior that you'd expect?
That parent is the global variable (https://developer.mozilla.org/en-US/docs/Web/API/Window/parent). If you look at the output, it's a window object, likely your current page. At the moment, there's no direct communication between components, even when nested.
That parent is the global variable (https://developer.mozilla.org/en-US/docs/Web/API/Window/parent). If you look at the output, it's a window object, likely your current page. At the moment, there's no direct communication between components, even when nested.
@SimoTod Oh. Lol. I should have realized that.
Is there a proposal for a shared state feature? Since Alpine.js doesn't "break the DOM", you can do something like this in the meantime:
<div x-data='{myparent: "I am in the parent"'>
<div class="sharedStateVarible"></div>
<!---------------------------------------------------------------->
<!-- Alpine "component" inserted by server side template engine -->
<div x-data='{myvar: "Hello World"}'>
<div class="sharedStateVarible"></div>
<button type="button" onclick="changeGlobalState(this.innerText,'sharedStateVarible');">
<div x-text="myvar"></div>
</button>
</div>
<!---------------------------------------------------------------->
</div>
<script>
function changeGlobalState(x, y) {
var myClasses = document.getElementsByClassName(y);
for (var i = 0; i < myClasses.length; i++) {
myClasses[i].innerHTML = x;
}
}
</script>
If your goal is to share state between components you can use a third party library called spruce (https://github.com/ryangjchandler/spruce).
@pandichef Open an issue on the Spruce repo if you need any help 🤙🏼
All HTML codes will become very large. How to split modules is a problem that every framework will encounter. How does Alpine apply the HTML code of another file?
All HTML codes will become very large. How to split modules is a problem that every framework will encounter. How does Alpine apply the HTML code of another file?
apply the HTML code in another file is too difficult on an existing basis, try it as a web component for a block code to reuse that maybe easier!
Hey,
From what I can see Alpine does not include any sort of concept of components (in the same way that something like React/Vue would handle them) this makes sense given it's use with Livewire and that it would be used in includes/partials.
I just wanted to confirm this though and if I am correct I wondered if you would be interested in a PR updating the "Read Me" and maybe a reference to some sort of HTML includes library that could be used on static projects for people who are un-familiar with this kind of thing.
Cheers.