mithril-vndb/docs/withAttr.md

2.8 KiB

withAttr(value, callback)


API

Creates an event handler. The event handler takes the value of a DOM element's property and calls a function with it as the argument.

This helper function is typically used in conjunction with m.prop() to implement data binding. It is provided to help decouple the browser's event model from application code.

m.withAttr(value, callback, thisArg?)

Argument Type Required Description
value String Yes The name of the attribute or property whose value will be used
callback any -> Boolean? Yes The callback
thisArg any No An object to bind to the this keyword in the callback function
returns Event -> Boolean? An event handler function

How to read signatures


How to use

// standalone usage
document.body.onclick = m.withAttr("title", function(value) {
	console.log(value) // logs the title of the <body> element when clicked
})

Typically, m.withAttr() can be used in Mithril component views to implement two-way binding:

var title = m.prop()

var MyComponent = {
	view: function() {
		return m("input", {
			oninput: m.withAttr("value", title),
			value: title()
		})
	}
}

m.mount(document.body, MyComponent)

Predictable event target

The m.withAttr() helper reads the value of the element to which the event handler is bound, which is not necessarily the same as the element where the event originated.

var url = m.prop()

var MyComponent = {
	view: function() {
		return m("a[href='/foo']", {onclick: m.withAttr("href", url)}, [
			m("span", url())
		])
	}
}

m.mount(document.body, MyComponent)

In the example above, if the user clicks on the text within the link, e.target will point to the <span>, not the <a>.

While this behavior works as per its specs, it's not very intuitive or useful most of the time. Therefore, m.withAttr uses the value of e.currentTarget which does point to the <a>, as one would normally expect.


Attributes and properties

The first argument of m.withAttr() can be either an attribute or a property.

// reads from `select.selectedIndex` property
var index = m.prop(0)
m("select", {onclick: m.withAttr("selectedIndex", index)})

If a value can be both an attribute and a property, the property value is used.

// value is a boolean, because the `input.checked` property is boolean
var value = m.prop(false)
m("input", {onclick: m.withAttr("checked", value)})