GithubHelp home page GithubHelp logo

alpinejs / alpine Goto Github PK

View Code? Open in Web Editor NEW
26.9K 26.9K 1.2K 7.37 MB

A rugged, minimal framework for composing JavaScript behavior in your markup.

Home Page: https://alpinejs.dev

License: MIT License

JavaScript 19.70% HTML 80.30%

alpine's People

Contributors

ahmedkandel avatar austenc avatar browner12 avatar calebporzio avatar ekwoka avatar gdebrauwer avatar gjcourtney avatar hugodf avatar jameschensmith avatar januridp avatar jasonlbeggs avatar jokarz avatar jonaskuske avatar joshhanley avatar jreviews avatar kevinbatdorf avatar keyurshah avatar markfirmware avatar markjaquith avatar marvinified avatar matsa59 avatar mauroreisvieira avatar muzafferdede avatar noahziheng avatar philippbosch avatar pminne avatar ryangjchandler avatar simotod avatar thormeier avatar zupolgec avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

alpine's Issues

x-cloak is not getting removed

I am using livewire with alpinejs, which works smoothly for a dropdown menu inside each row of a livewire table, but after adding x-cloak directive, the livewire loaded pages includes the x-cloak directive and that is not been removed when new components are discovered by alpinejs.

at the moment I am tackling this problem with the following
image

[Events] x-on:submit and x-on:submit.prevent does not work

Let us say I have a form:

        <form>
            <input type="text">
            <button type="submit">Do something</button>
        </form>

If I want to prevent the default submit, the following code does not work:

        <form x-on:submit.prevent>
            <input type="text">
            <button type="submit">Do something</button>
        </form>

And neither does:

        <form x-on:submit="event.preventDefault();">
            <input type="text">
            <button type="submit">Do something</button>
        </form>

Am I doing it incorrectly, or maybe it is not implemented yet (if so I would gladly try to contribute myself).

EvalError: Refused to evaluate a string as JavaScript

Hi,

i'm using alpinejs just to open and close the menu of the website with x-data, x-show and x-bind:style to animate a few things.

Probably not directly related to this library but maybe someone can help me or maybe this will help someone else. Anyway It was working fine on local and then on the production server this error came out in the js console of the browser and of course the menu wasn't working.

EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self' http: https: data: blob: 'unsafe-inline'".

Reactivity lost on v1.5 โ†’ v1.6 when binding to a function returning boolean

This was working in version smaller or equal to 1.5.0 and since 1.6.0 it's no longer working:

<div x-data="test(true)">

  <button @click="toggle()">Press me</button>

  <input type="text" x-bind:value="isSet" />

  <input type="text" x-bind:value="getIsSet()" />

</div>
function test(status) {

  return {
    isSet: !!status,
    toggle() {
      this.isSet = !this.isSet
    },
    getIsSet() {
      return this.isSet
    }
  }

}

Reading the isSet value from the data-set is reactive and updated correct. But binding the return value from getIsSet(), it's not updated โ€“ even though is initialized correct. When running the same code with v1.5, it's working as expected.

You can test it in this fiddle.

Undeclared model object keys default to undefined instead of empty string

Take a look at the following examples:

Alpine.js - https://codepen.io/jreviews/pen/NWPMVMz

Vue.js - https://codepen.io/jreviews/pen/wvBjbNX

In Alpine.js, undeclared model object keys default to undefined, while in Vue.js they default to an empty string. Is it possible to have a similar behavior as Vue.js? It's ok to add the model keys to the object if there's a handful, but if there are dozens or hundreds it gets more complicated.

Stopped working on IE11

Hello,

It seems that after the transition to rollup and newer features, alpinejs is not working in IE11 with the current polyfills.

I am getting the error:

Expected ')'

at this line in utils.js

export function walkSkippingNestedComponents(el, callback, isRoot = true) {

I then tested on a branch after the transition to rollup (1.1.3) and got it to work by changing babel.config.js to the following

module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        targets: {
          browsers: "> 0.5%, ie >= 11"
        },
        modules: false,
        spec: true,
        useBuiltIns: "usage",
        forceAllTransforms: true,
        corejs: {
          version: 3,
          proposals: false
        }
      }
    ]
  ]
};

this increases the build size, but gets it to work for testing purposes.

I then tested the same configuration on the current build (1.7) and I now get the following error

Uncaught (in promise) TypeError: Cannot create property for a non-extensible object

Seems like an error with the proxy polyfill when researching that error.

<script src="https://cdn.jsdelivr.net/npm/[email protected]/proxy.min.js"></script>

I also tested by adding Laravel Mix back and the same object error still occurs.

Wondering if anyone else has gotten a recent build to work with IE11?

Thanks.

Why not include Polyfills for IE11 in core project?

I know IE11 is a pain, but considering it's still shipped with Windows 10 chances are it'll be around until 2023 or even 2025 :(
@calebporzio could you advise you don't just include the polyfills for IE11 in the core of alpine?
(to me this feels like the kind of "invisibility" alpine and livewire are all about)

multiple data targets

Loving project-x!

I've been able to test out many of the things in stimulus and recreate them. One issue i'm not sure how to handle referencing repeating row elements.

Scenario: displaying the subtotal from a list of shopping cart items. I'd like to loop over a data-attribute value containing the subtotal of each line item.

Here's an example in VueJs

https://stackoverflow.com/questions/44063337/add-all-values-in-vuejs

In Stimulus, elements having the same name can be accessed through this.[name]Targets and I would typically loop over the resulting array and sum the data attributes.

image

Perhaps $refs can be expanded to access multiple items having the same name as an array?

Open to other ways as well. Thanks!

P.S. I wasn't sure the best place to ask this (github or twitter). A subtopic in the new livewire forum might be useful.

Nesting does not work

Looks very nice. Tried it immediately in the navigation section of my project. Works great already! But unfortunately I stumbled on some issues when trying to make a nested dropdown menu.

<div x-data="{ open: false }">
    <button x-on:click="open = true">Open Dropdown</button>

    <ul
        class="hidden"
        x-bind:class="{ 'hidden': ! open }"
        x-on:click.away="open = false"
    >
        Dropdown Body
        <div x-data="{ another: false }">
            <button x-on:click="another = true">Open another Dropdown</button>

            <ul
                class="hidden"
                x-bind:class="{ 'hidden': ! another }"
                x-on:click.away="another = false"
            >
                Another dropdown Body
            </ul>
        </div>
    </ul>
</div>

Opening the first dropdown works, but opening the second fails because of the error:

ReferenceError: another is not defined

catch error while using x-if

toggle x-if expression the console will receive

alpine.js:1 Uncaught TypeError: Cannot read property 'isSameNode' of null
    at MutationObserver.observe.childList (alpine.js:1)
MutationObserver.observe.childList @ alpine.js:1
alpine.js:1 Uncaught TypeError: Cannot read property 'remove' of null
    at alpine.js:1
    at alpine.js:1

Is this a bug ? Or it's not supposed to using like this?

[Idea] Add ability to define a component controller

This might be something that goes a little against the project's philosophy, but I'll put it out there nonetheless.

I think it would be neat if we could (optionally) define a controller class/object/whatever for Alpine, that would bind to existing HTML in the same way Stimulus does.

I'm envisioning something like the following (basically a modified copy of Stimulus's conventions):

class MyController extends AlpineController {

    data = { testInput: null, testCheckbox: null, submitted: false };

    connected() { // lifecycle hooks
        this.data;
        this.$refs;
    }

    async submitForm($event) { // long-form event handlers
       await fetch(...);
       // do a million other things
       this.data.submitted = true;
    }
}

Alpine.controller('my-controller', MyController);
<div x-controller="my-controller">
    <form @submit="submitForm"> <!-- all of the controller's methods and data in scope here -->
        <input type="text" x-model="testInput">
        <select x-model="testSelect">
            ...
        </select>
        <div x-show="submitted">We submitted the form!</div>
    </form>
</div>

I'm doing something similar with an actual Stimulus + alpine combo, but there are some pain points (very verbose html, communication between a Stimulus controller and alpine).

I've looked through alpine's source, but I didn't grok it fully yet, so I'm unaware of any technical challenges that could arise, but would love your thoughts!

Automated testing via CI

Hey again @calebporzio

I've watched this repository for a while now and noticed the growth of the entire thing, quite amazing!

Is there any reason why no CI has been integrated yet? With the amount of issues and especially PRs created, it might make sense to add a CI to automatically execute the already existing tests on new commits/PRs.

Personally, I use Travis CI (https://docs.travis-ci.com/) for such things, as it's free for open source projects and has a nice GitHub integration.

What do you think?

Regards

[FR] Nested transitions

It would be great to be able to nest transitions. A common use case is a modal, where you want to fade-in the background before the content. This is an example in Vue.

[Question] How to toggle the 'disabled' atrribute with Project-X?

If we have a <button>click me</button>, I want to add the disabled attribute using a condition. I want something like <button x-toggle:disabled="myVar">click me</button>. When myVar is falsy, the attribute will not be rendered and viceversa. Instead of myVar it can also be any javascript that return falsy or truthy values.

I'm currently getting this behaviour by using x-bind:class but I was wondering if one could toggle attributes.

@click events don't trigger in x-html rendered nested elements

The @click event in the code below doesn't trigger after this.tasks changes. It does work when the renderList function runs on component initialization.

renderList() { 
	return this.tasks.map(task => {
	    return `
			<div>
			 	<span x-text="'${task}'"></span> 
			 	<button @click="removeTask('${task}')">Remove</button>
			</div>
		`
	  }).join('')
}

However, when adding the @click event to the parent 'div', then it works:

renderList() { 
	return this.tasks.map(task => {
	    return `
			<div @click="removeTask('${task}')">
			 	<span x-text="'${task}'"></span> 
			 	<button>Remove</button>
			</div>
		`
	  }).join('')
}

Struggling with x-class binding

First of all, I love this. This declarative approach is why I fell in love with Vue.js in the first place, and the bigger and more robust Vue gets, the less I want to use it on small projects.

Okay so I'm trying to make buttons that hide themselves when you click them, and I must be doing something simple and dumb, but I can't get it to work. Here's my fiddle: https://jsfiddle.net/c6at2e7z/

Any ideas?

How to use $refs proxy?

Let's say I have the following HTML:

<body x-data="{task: {id: '', label: ''}}">
    <section id="add-task-container">
        <form x-on:submit.prevent>
            <input type="text" x-model="task.label">
            <button type="submit" x-on:click="$refs.listTasks.appendChild(taskToDOM(task, $refs.taskTemplate))">Add task</button>
        </form>
    </section>
    <section id="list-tasks-container" x-ref="listTasks">

    </section> 

    <template id="task-template" x-ref="taskTemplate">
        <section class="task">
            <input type="checkbox" class="task-check">
            <p></p>
        </section>        
    </template>
</body>

When trying, in my taskToDOM function, to do something like this:

function taskToDOM(task, template) {
    const div = template.content.querySelector('.task');
    const node = document.importNode(div, true)
    .....
}  

I have got the following error:
Uncaught TypeError: Illegal invocation

I am not very used to JavaScript Proxies, so maybe I am doing something wrong?

`x-bind:class` doesn't watch nested keys

Hello,

first of all, thank you for this amazing piece of software!

I started playing around with and noticed that at least x-bind:class doesn't watch nested keys. Code to reproduce:

<div x-data="{ foo: { bar: false }, baz: false }">
    <!-- Doesn't work, the class doesn't get attached on click. -->
    <p x-bind:class="{ 'works': foo.bar }" x-on:click="foo.bar = true">
        Lorem ipsum dolor sit amet
    </p>

    <!-- Shows true when upper paragraph has been clicked. -->
    <button x-on:click="console.log(foo.bar)">Check foo.bar</button>

    <!-- Works, the class gets attached properly as soon as clicked. -->
    <p x-bind:class="{ 'works': baz }" x-on:click="baz = true">
        Lorem ipsum dolor sit amet
    </p>
</div>

The button shows that the nested key is indeed being changed, but x-bind doesn't seem to recognize this change.

As a workaround, one could just avoid nested keys or use functions to achieve this, but that doesn't seem very practical.

Any ideas?

Regards

How work with webpack and other build tools

As I understand it, the functions of the components must be global and located in the window object. But then what about modules, iife and build tools like Laravel Mix? Tell me about usage and file structure, please.

Add .prevent modifier to click-handler

Very nice framework! :-) Would be very nice to have "prevent" modifier on a click handler, that way it can be used on anchor-elements.

Example:
<a class="nav-link" href="#" x-bind:class="{ 'active': tab === 'view' }" x-on:click.prevent="tab = 'view'">View</a>

The modifiers you have in Livewire could serve as an example:

  • stop Equivalent of event.stopPropagation()
  • prevent Equivalent of event.preventDefault()

Add a copy of the MIT license

package.json says Alpine.js is licensed under the MIT license, but there's no copy of the license in the repository. It's good practice to add a copy of the license to the repository to make this clear. This also lets GitHub detect it ๐Ÿ™‚

Using the parent variable after nested components

I'm have a component and then declaring nested components inside.

Once I use a data variable after a new nested component is declared, the variable doesn't work. Here's an example:

https://codepen.io/kjshah/pen/df81e5331e12140ac50ecb342dedfb61

<div x-data="values()">
  <div class="font-semibold">This Doesn't Work</div>
  
  <div x-data="{name: 'blue widget'}">
    Name: <span x-text='name'></span>
  </div>
  
  <hr>
  (total should show here)
  Total: <span x-text="total"></span>
</div>
  
--------------------------------------------------
  
<div x-data="values()">
  <div class="font-semibold">This Works</div>
  
  Total: <span x-text="total"></span>
  
  <div x-data="{name: 'blue widget'}">
    Name: <span x-text='name'></span>
  </div>
</div>
<script>
function values() {
  return {
    total: 1,
  }
}
</script>

Project goals/ motivations

You get to keep your DOM, and sprinkle in behavior as you see fit

This project reminds me of KnockoutJs and StimulusJs (both which I'm a big fan). So I got curious to know a little bit more about the motivations behind it.

For someone like me, that likes the "traditional" approach of server-side rendering and progressive enhancement instead of javascript-centric applications is very interesting to see other frameworks providing this kind of experience to kinda "fill jquery's shoes".

Can I assume that this project relates to both ko and stimulus in regards of not trying to take control of the whole app and instead is meant to be used with a server-side rendering approach (or something like that)? And if so, what are the main differences from those aforementioned frameworks?

PS: Also, it seems that there's some hint of integration with turbolinks and wanted to ask if there are plans to integrate with unpoly as well.

Listen to a custom event and pass event

Seeing if it would be possible for x-on to listen to a custom event and pass the event to the expression function.

In the example below, I'm trying to pass data between components.

https://codepen.io/kjshah/pen/fe0ecb50b49d61a0eb55eaeb9c3bf7d2?editors=1011

It would be great if the following example could work, with cart-quantity-updated being the custom event (listened to) and updateTotal(event) being called when the event occurs.

<span x-text="total" x-on:cart-quantity-updated="updateTotal(event)"></span>

Add x-else and x-unless conditions

Are x-else and/or x-unless planned? Would be great to have them! Let me know if you want some help on these, happy to pair up or submit a PR :)

Nested components cannot access external data

Hi @calebporzio,
thanks for the amazing work so far. I was having a go with alpinejs and I noticed that, when there are nested components, the internal component cannot access the scope of the external one.

For example,

<html>
  <head>
    <script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.js" defer></script>
  </head>
  <body>
    <div x-data="{ foo: 'bar', foo2: 'BAR' }">
      <span x-text="foo"></span>
      <div x-data="{ foo: 'bob' }">
        <span id="s1" x-text="foo"></span>
        <span id="s2" x-text="foo2"></span>
      </div>
    </div>
  </body>
</html>

I would expect span#s2 to display 'BAR' or, in alternative, i would expect to be able to reference foo2 in the internal data structure.

I'm happy to work on a PR for this but I just wanted to check with you first in case this behaviour is expected and you do not want components to access external scopes.

Thanks,
Simone

Lifecycle Methods

Well done, you guys! I'm giving up all these Vue, React and Stimulus ) will keep an eye out!
Does Alpine lifecycle methods, like stimulus connect/disconnect?

Multiple executions when loading through webpack

Hello,

I am trying to load alpine from webpack (laravel mix) given the instructions

import Alpine from 'alpinejs'
Alpine.start()

on my page, if i use this code

<div x-data="{}">
  <div x-on:click="console.log('hello')">Click here</div>
</div>

i see 2 executions in my console log

image

This doesn't happen if I load alpine with the script tag outside of webpack.


Also, trying to organize alpine components in webpack, and wondering if there were any best practices.

I got it to work by assigning custom functions to the window object. not a problem, just want to make sure this is the proper way.

app.js

import * as product from './alpine/product'
window.product = product;

alpine/product.js

export function add() {
  return {
    name: 'blue widget',
}

and then declaring as follows

index.html

<div x-data="product.add()">
   <div x-text="name"></div>
</div>

Thanks!

X-Ref not working

I am trying to do the following

<div x-ref="something"></div>
addChild() {
    var btn = document.createElement("BUTTON");
    btn.innerHTML = "CLICK ME";     
    this.$refs.something.appendChild(btn); 
}

and I get this

Uncaught TypeError: Cannot read property 'something' of undefined
    at Proxy.addChild (test-file:96)
    at Proxy.open (test-file:53)
    at eval (eval at <anonymous> (project-x.min.js:1), <anonymous>:1:15)
    at project-x.min.js:1
    at t.value (project-x.min.js:1)
    at t.value (project-x.min.js:1)
    at HTMLInputElement.<anonymous> (project-x.min.js:1)

[Feature Request] x-watch

In this example; there is a slider (let's say flickity), we want to create a custom UI that will track the active slide. AlpineJS would be good to do this because we can minipulate the UI based on the active slide.

Let's say for example on each slide we have a UI that has the title of the slide, we can use <div @click="activeSlide = 1; activeTitle = 'Projects'">Projects</div>

Then we can use x-watch to watch the activeSlide and run a function when it changes, I'm unsure of the best implementation for this x-watch:activeSlide="function" or x-watch="{ activeSlide: function } so for example we could do x-watch="{ activeSlide: $el.select(value) }" value would be the value of the variable. I know the syntax is completely wrong, but it's the best way I can think of demostrating my thinking.

Working with a Date Object is difficult

I am working on a Project-X Date Picker. I can define a date object by defining a method that returns the date object

today() { return new Date() }

where I run into issue is when I want to create mutable properties for the day, month and year. I tried this two ways. First I trying defining date method that returns a object that has 3 child objects (day, month and year) with each one of those containing a a selected and current property. This does work but I cannot mutate the properties.

 date() { 
                    return {
                        day: {
                            current: this.today().getDate(),
                            selected: this.today().getDate()
                        },
                        month: {
                            current: this.today().getMonth(),
                            selected: this.today().getMonth()
                        },
                        year: {
                            current: this.today().getFullYear(),
                            selected: this.today().getFullYear()
                        },
                    }
                },
selectDay() {
    this.date().day.selected = 20;
    console.log(this.date().day.selected) //logs current day (12) instead of 20
}

Secondly I defined properties for each (daySelected, dayCurrent for example) but it tells me that today() is not a method

today() { return new Date() },
dayCurrent: this.today().getDate(),
daySelected: this.today().getDate()

I'm not sure if there is something I am missing here or something in Project-X needs to change.

Remove event listeners on disconnect

It might be out of the scope of the project, but wondering of the usefulness to remove event listeners on disconnect?

If using with turbolinks, pjax or unpoly, it seems there's a chance for a memory leak with stranded event listeners.

And if project-x is used in a turbolinks type of environment, would it be helpful to have init(), connect() and disconnect() functions that can sit inside the x-data function?

Get $refs in functional component way

Hi, how i can get $refs in function?

function behavior() {
  console.log($refs) // <- ??? it's window object
  return {
    isShow: false,
    handleMouseMove(e, { img }) {
      $refs.img.style.transform = `translate3d(${e.pageX}px, ${e.pageY}px, 0)`
    }
  }
}

Add x-for for loop

Is it possible to add to alpinejs the loop like vue v-for

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>

Thanks

[Feature Request] `x-enter` / `x-exit`

Looking at adding an event for when a dom element enters the current viewport.

This can be done in one of two ways,

  1. InteractionObserver
  2. MutationObserver with listeners on load, scroll, & resize

The issue with InteractionObserver is that it does not support IE 11. The polyfill would most likely be several times the size of alpine altogether, even gzipped.

The issue with MutationObserver is that it requires a lot more code (more to maintain), and requires some sort of throttle (usually 100ms) to not thrash on every scroll pixel. You can see a couple of examples here and here.

We could do something like x-enter / x-exit and we could implement the once feature as a future expansion. I'm not overly picky on this, and am fine with whatever syntax @calebporzio would prefer.

Ideally, I'd like to see it work similar to x-on where it, the JavaScript expression set as it's value is executed.

The correct answer here might be to not push this feature inside core.

I'm going to start thinking about this a little bit more this week. If anyone would like to take a stab at it, go for it. I'll probably get more serious about it sometime next week.

This feature is a blocker for me to entirely replace a custom JavaScript implementation, which I really would like to nuke into oblivion.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.