this' attributes don't get detected in x-on:click - alpine.js

This works :
<input
id="chk-products"
name="chk-products"
type="checkbox"
x-on:click="showProducts = document.getElementById('chk-products').checked">
But this doesn't :
<input
id="chk-products"
name="chk-products"
type="checkbox"
x-on:click="showProducts = this.checked">
I was wondering why this isn't available in alpinejs's directives ?

With Alpine.js you don't have to inspect/mutate the DOM manually. It uses the data model: first you define some data, then you bind it to some input elements and let Alpine.js handle the DOM mutations, etc.
<script defer src="https://unpkg.com/alpinejs#3.x.x/dist/cdn.min.js"></script>
<div x-data="{showProducts: false}">
<input type="checkbox" x-model="showProducts" /> Show products
<div x-show="showProducts">Products are shown.</div>
<div x-show="!showProducts">Products are hidden.</div>
</div>
The this keyword is available inside a component created with Alpine.data() global function.

The x-on:click directive in Alpine.js is designed to execute a JavaScript expression when an element is clicked. In this case, the expression is trying to access the checked state of the checkbox element, which can be done more directly by using the this keyword to access the element that the directive is applied to. Unfortunately, Alpine.js does not support the use of the this keyword in its directives.

Related

how to pass callback function in component? (laravel alpine.js)

I make a draft implementation for my reusable input component.
The code below obviously throws an error.
Question is how to pass the $event back to register blade to get or log the value of the input?
register.blade.php
<div>
<x-input onChange="(value) => {console.log('value', value)}"></x-input>
<div/>
input.blade.php
#props(['onChange' => 'null'])
<input x-on:change="{{ $onChange($event) }}">
A few things here.
First off, your markup is wrong. You have a the closing slash at the wrong end of the closing div. Should be </div> not <div/>.
Then you're using x-on without x-data. Alpine only picks up components with the x-data attribute.
Finally, events propagate automatically, so you could just listen on the parent instead:
{{-- register.blade.php --}}
<div x-data>
<x-input x-on:change="console.log('value', $event.target.value)" />
</div>
{{-- input.blade.php --}}
<input {{ $attributes }}>
I learned we could just achieve this through Alpine.Js dispatch. I don't need to pass onClick props via Laravel component. I just simply use dispatch to listen the event (x-on).
What I like in this implementation is that,
aside of event information, passing of extra data is easy
you don't have to use Laravel props and assigned unnecessary props in the tag.
register.blade.php
<div>
<x-input x-on:custom-input="console.log('your values =', $event.target.newValue)"
></x-input>
<div/>
input.blade.php
<input x-on:change="$dispatch('custom-input', { newValue: $event.target.value })">
you can pass "key" prop to distinguish each component.

Is it possible to exclude an element from kendo ui transformation?

I want to exclude an html-element from getting transformed to a kendo ui widget.
Is this possible? Maybe via css class or so?
Example:
https://jsfiddle.net/8L4zg92x/
<input type="file" class="first"> // => KendoUpload
<input type="file" class="second"> // => plain Html-File-Upload
--
i'm not able to change the jquery selector.
$(document).ready(function() {
$("input[type=file]").kendoUpload();
);
I realise this is a different approach which might not be practical in your situation, but using declarative initialization, instead of imperative (jQuery) initialization would give you what you want:
<body>
<div id="outer">
<input type="file" class="first" data-role="upload">
<input type="file" class="second">
</div>
<script>
kendo.init($("#outer"));
</script>
</body>
See Initializing with MVVM for more information on using this approach.
Example: https://dojo.telerik.com/eLOWaluL
just in case someone has the same problem, but can edit the selector. Here is an easy way to don't select the second input-field:
$(function() {
$("input[type=file]:not('.second')").kendoUpload();
});

Autocomplete datalist on Thymeleaf

I'm building a view with Thymeleaf templates, which contains a form that provides a way to bind the value of my inputs with the attributes passed in the model. The backend was developed using Spring 4.
The following snippet includes an autocomplete datalist with the data of the namelist object, which was added to the model as an attribute. Said namelist is an ArrayList of a class with the fields int id and String name.
<form th:action="#{/}" method="POST" th:object="${example}">
<div class="form-group">
<input list="names" class="form-control" id="nameinput" th:field="${example.num.id}"> </input>
<datalist id="names">
<option th:each="row : ${namelist}" th:value="${row.id}" th:label="${row.name}">
</datalist>
<button>submit</button>
</div>
</form>
The value of the selected option is already bound to example.num.id, which is the expected and desired behaviour. However, when loading the view on a web browser (tested on latest Firefox and Chrome), it is represented like this:
As you can see, the id's are showing. However, I'm trying to emulate the behaviour of a <select>; the value should not be shown, just the text or label.
Is there a better way to achieve this? Am I not using the datalist properly?

Blade templating components?

I have a input wrapper, (input-wrapper.blade.php)
<div class="form-group">
#yield('input')
</div>
Called via:
#include('input.checkbox')
The checkbox file looks like:
#extends('input-wrapper')
#section('input')
<input type="checkbox" value="1">
#endsection
The issue I am having is when I call this with multiple inputs (I have one for different input types):
#include('input.checkbox')
#include('input.textarea')
....
I just get a rendering of the first item (checkbox) multiple times. i'm hoping to render each type of input.

Can you call ko.applyBindings to bind a partial view?

I'm using KnockoutJS and have a main view and view model. I want a dialog (the jQuery UI one) to popup with another view which a separate child view model to be bound to.
The HTML for the dialog content is retrieved using AJAX so I want to be able to call ko.applyBindings once the request has completed, and I want to bind the child view model to just the portion of the HTML loaded via ajax inside the dialog div.
Is this actually possible or do I need to load ALL my views and view models when the page initially loads and then call ko.applyBindings once?
ko.applyBindings accepts a second parameter that is a DOM element to use as the root.
This would let you do something like:
<div id="one">
<input data-bind="value: name" />
</div>
<div id="two">
<input data-bind="value: name" />
</div>
<script type="text/javascript">
var viewModelA = {
name: ko.observable("Bob")
};
var viewModelB = {
name: ko.observable("Ted")
};
ko.applyBindings(viewModelA, document.getElementById("one"));
ko.applyBindings(viewModelB, document.getElementById("two"));
</script>
So, you can use this technique to bind a viewModel to the dynamic content that you load into your dialog. Overall, you just want to be careful not to call applyBindings multiple times on the same elements, as you will get multiple event handlers attached.
While Niemeyer's answer is a more correct answer to the question, you could also do the following:
<div>
<input data-bind="value: VMA.name" />
</div>
<div>
<input data-bind="value: VMB.name" />
</div>
<script type="text/javascript">
var viewModels = {
VMA: {name: ko.observable("Bob")},
VMB: {name: ko.observable("Ted")}
};
ko.applyBindings(viewModels);
</script>
This means you don't have to specify the DOM element, and you can even bind multiple models to the same element, like this:
<div>
<input data-bind="value: VMA.name() + ' and ' + VMB.name()" />
</div>
I've managed to bind a custom model to an element at runtime. The code is here: http://jsfiddle.net/ZiglioNZ/tzD4T/457/
The interesting bit is that I apply the data-bind attribute to an element I didn't define:
var handle = slider.slider().find(".ui-slider-handle").first();
$(handle).attr("data-bind", "tooltip: viewModel.value");
ko.applyBindings(viewModel.value, $(handle)[0]);
You should look at the with binding, as well as controlsDescendantBindings http://knockoutjs.com/documentation/custom-bindings-controlling-descendant-bindings.html

Resources