Or simpler, how do I implement an equivalent of the code below in node js?
selectedRadio = document.querySelector('input[name="device"]:checked').dataset.name;
I'm using Node js for backend of an app with Express.js and BodyParser.
I was able to access HTML elements with their Names with req.body.elementName, but I have trouble getting value from the code above.
The DOM doesn't exist in Node. There is no body or document because there is no website in the backend. That means accessing a DOM element by document.querySelector() will not work because document doesn't exist.
You should be passing the values directly to your Node application, instead of passing HTML Elements.
Like Zammy said, there is no DOM. Just try using events for this.
just give your checkbox the onChange property and add the function you want to handle your event with.
<input
type="checkbox"
onChange=YOUR JS_EVENT_CODE
/>
There you could bind an existing function or just insert sth. like an arrow function.
Related
Svelte’s templating language is great, in that it looks like HTML. However, for highly dynamic content I need to be able to use the full power of JavaScript, not just #if and #each. For example, given a tree data structure, I want to generate hierarchical table headings. (Demo) In React most apps use JSX templates, but you can drop down to createElement if you need to. Is there a similar path for Svelte? Am I missing something obvious?
If you need access to the DOM node, you can:
Add bind:this={node} to get access to the DOM node:
<script>
import {onMount} from 'svelte'
let node
onMount(() => {
const dynamic = document.createElement('a')
dynamic.innerHTML = "Click me!"
node.appendChild(dynamic)
})
</script>
<div bind:this={node}/>
Add a use directive, this will also get you access to the raw DOM node
<script>
function ninja(node) {
node.innerHTML = "Kawabunga!"
}
</script>
<div use:ninja/>
I would look at the <svelte:self> element, which allows you to create elements that call themselves recursively.
https://svelte.dev/tutorial/svelte-self
How can I add HTML objects to an event?I would like to do something like this:
Template.Schedule.events({
'dblclick .mycol' (event){
event.target.childNodes.append("<strong>Test</strong>");
}
});
I know I could style it and change the innerHTML and so on for the given example, but I actually want to add other HTML objects, like a select-tag, how can I do that?
The vanilla JS way
You could use innerHTML here to change the html content of the clicked element:
'dblclick .mycol' (event){
const target = event.currentTarget
target.innerHTML = target.innerHTML + "<strong>Test</strong>"
}
If you want to manipulate the parent in the event you can use outerHTML
The jQuery way
Your approach of using append is requiring jQuery:
'dblclick .mycol' (event){
$(event.currentTarget).append($("<strong>Test</strong>"))
}
Bonus: Optimization for using jQuery
In a meteor blaze template-events each event has a reference to the template instance. This template instance keeps a reference to a jQuery object and it's part of the DOM that it manipulates.
template.$ returns a jQuery object of those same elements. jQuery
objects are similar to arrays, with additional methods defined by the
jQuery library.
The template instance serves as the document root for the selector.
Only elements inside the template and its sub-templates can match
parts of the selector.
You can access it via templateInstance.$ if your seconds event parameter is namend templateInstance. With
'dblclick .mycol' (event, templateInstance){
templateInstance.$(event.currentTarget).append($("<strong>Test</strong>"))
}
This saves jQuery the need to traverse the whole DOM, makes it more efficient on large documents.
The Meteor Blaze way
Now these are neat little tricks when there is need for manipulation on a small scale. However, you may want your app to be scalable and profit all the time from the Blaze rendering engine.
In such cases you may rather want to generate a way of dynamically inserting templates.
Consider the following template, that is nowhere imported yet:
rowcontent.html
<template name="rowcontent">
<strong>Test</strong>
<p>someData{{someData}}</p>
</template>
rowcontent.js
import './rowcontent.html' // currently just the import
You can dynamically add it at runtime to an element using Blaze.renderWithData so:
'dblclick .mycol' (event, templateInstance) {
import './rowcontent.js' // use the right path here
Blaze.renderWithData(Template.rowcontent, {someData: 'toBePassedToRowContent'}, event.currentTarget)
}
which will result in:
This is my col Test
someDatatoBePassedToRowContent
The advantage of this approach is that you can pass the data to the template and have all the reactive benefits remaining, thus handle the newly added template like any other template in Meteor.
Alternatives
Declarative dynamic templates using Template.dynamic
Have a SAPUI5 application. Html view created by xml. JavaScript controllers. Some elements of this application, e.g. buttons are created somewhere dynamically within the controllers of the respective views. I.e. cannot use the id of an element to get it in the controller because the ids are dynamically created. Would like to get those dynamically created elements of the application to modify them, e.g. modify the buttons. What's the best way to trace a dynamically created element back to its code where it's created? E.g. how to trace a button back to it's origin in the JavaScript controller? It's a huge application and a view has multiple controller. I'm not just lazy.
The render function in the component's renderer class is what (eventually) creates the DOM element. You can inject a debugger statement into it like so:
let __buttonRender = sap.m.ButtonRenderer.render;
sap.m.ButtonRenderer.render = function() {
let control = arguments[1];
console.log('Creating button: ', control.sId);
debugger;
return __buttonRender.apply(this, arguments);
}
You can probably modify the control object based on the Id here. I'm not exactly sure what your end goal is here. The renderer is probably taking attributes and data from XML, so if you want to modify the buttons, I'd do it at the data source. The above could would allow you to hack the model before it reaches the DOM, but it's kinda nasty.
I'm using Polymer 2.0 and I have a dom-repeat for different to-do cards. What I want to do is remove the card when I click on it.
So I tried this on-tap=deleteNote([[index]]) which uses the index from the dom-repeat. However Polymer doesn't execute the function.
What am I doing wrong?
Another solution could be the dataset object within the event.target. You can define your properties with the data- prefix:
<div on-tap="doSomething" data-item$="[[item]]"></div>
And within your doSomething() listener you can get the dataset object:
doSomething(event) {
const item = event.target.dataset.item;
...
}
You can access the model via the event argument's model property.
So you can access the index from event.model.index.
Well, I am aware you can't. There are many discussions about that on the internet.
Of course, there is a way how to pass argument to function. You can save [[index]] in attribute of element and then get the attribute when needed.
Example:
<div on-tap='_deleteNote' indexed$='[[index]]'>
Then in script:
_deleteNote(e) {
var index = e.target.getAttribute('indexed');
...
}
Once you get index, you can do whatever you want with it.
Don't forget to extend Polymer gestures if you are not using hybrid elements in Polymer 2.0.
class Foo extends Polymer.GestureEventListeners(Polymer.Element) {}
More about it: https://www.polymer-project.org/2.0/docs/devguide/gesture-events#using-gesture-events
What is hybrid element: https://www.polymer-project.org/2.0/docs/devguide/hybrid-elements
on-tap does not appear to be implemented in Polymer 2.0. If you instead use on-click then it will work.
EDIT: see below comment.
I would like to use knockout.js in cross iframe binding. Existence of iframes is dictated by actual app structure I am working on.
This is the scenario (simplified):
Main window: Knockout.js included. window.top.DATA is a global container for data, ex. var DATA = { username: ko.observable('John') };
Module iframe window: Knockout.js also included. View wants do display data stored in window.top.DATA object, using code: <div data-bind="text: window.top.DATA.username></div>
What is the result?
DIV's innerHTML contains ko.observable().toString() contents instead of John.
The cause
Knockout.js is unable to recognize an observable created in parent frame while performing binding, because knockout checks if variable is observable with ko.hasPrototype by comparing references. Since prototypes are different between parent and child frame ko instances, it is impossible to bind values.
Solutions
The simplest solution would be writing something like: window.ko = window.top.ko || setupKO() on the top of script file. Unfortunately, in this case binding like with: window.someLocalObj is referencing to window.top instead of window - we are not able to access local variables and also local templates using template binding.
Another way to fix the problem is simply allow knockout to recognize observables as it should, what would allow observables to track dependency, bind values and just work well. Unfortunately I expect it might be difficult thing to achieve. What options do you see here?
Thank you for all your responses.
Edit
Knockout.js version: 3.2.0.
One solution is to use a single ko instance to handle main window and its frames elements at the same time. iframe elements are acessible through window.frames[frame_index].document:
var DATA = { username: ko.observable('John') };
ko.applyBindings(DATA);
ko.applyBindings(DATA, window.frames[0].document.body);
Working example: Plunker