LitElement does not update when attribute changed - javascript

I have very simple Lit component with an attribute.
I can change this attribute outside and Lit component receives new value and can display it, for example in the <input> tag.
This operation works as many times as I change the attribute. Problem occurs when I change the value manually in the <input>.
Component looks like this:
cmp.ts
import {html, css, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
#customElement('cmp-tmp')
export class CmpTmp extends LitElement {
#property({ type: Number })
dt = 0;
public render() {
return html`
<input value=${this.dt}>`;
}
}
index.html
<!DOCTYPE html>
<head>
<script type="module" src="./cmp.js"></script>
</head>
<body>
<cmp-tmp dt=""></cmp-tmp>
<button onclick="document.querySelector('cmp-tmp').setAttribute('dt', Date.now())">Set Date</button>
</body>
Playground
Steps to reproduce:
Click "Set Date" button -> attrbiute was changed and input received new value
Click "Set Date" button -> attrbiute was changed and input received new value
Type something in the input field
Click "Set Date" button -> attrbiute was changed, new value was displayed in the console but input didn't received new timestamp

If somebody has the same issue: . should be used to bind value property.
i.e. <input .value=${this.dt}>
More details here

Related

Grouping HTML elements and create a new eleme

Please consider I am having below codes which is a set of elements for selecting and showing date.
<div>
<input type="text" class="txt txtDate"/>
<input type="button" class="btn btnDate" value="Select from Calendar"/>
<span class="remainedDays"></span>
<div>
Here I have an input for entering date, a button for selecting date from a calendar, and a label which shows difference between selected date and current date. All calculations and form interactions is handling by JavaScript and jQuery.
Since I use this date picker in many forms I'm looking for a way to define this elements in a new element and use new element. If I can do this I will write less codes and any change in in definition of new element will be automatically applied in all forms.
I am looking for something like this:
<mydatepicker class="dt1"></mydatepicker> or <mydatepicker class="dt1"/>
which should be rendered in browser as
<div class="dt1">
<input type="text" class="txt txtDate"/>
<input type="button" class="btn btnDate" value="Select from Calendar"/>
<span class="remainedDays"></span>
<div>
You can create a custom element in Vanilla JavaScript, but really not worth the hassle, I suggest you start using JavaScript frameworks for this kind of thing.
But anyway, you can do it in vanilla javascript like this:
First create a JavaScript file (e.g, c-element.js) and extend the HTMLElement class. Inside it's connectedCallback method, write the HTML content you'd like to render.
Then add the script to your HTML file, and just use the custom element's tag!
Of course, this is just a really simple example, you can add to it however you want. You can read the documentation on creating custom elements here.
class CElement extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = `
<div class="c-element">
<div class="c-element__heading">
<h1> This is a custom element (CElement)</h1>
</div>
</div>
`;
}
}
customElements.define("c-element", CElement);
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<c-element> </c-element>
<script src="c-element.js"></script>
</body>
</html>
You need something like angular.js directive or Angular Component with pure JavaScript code.
You can create Web Component by extending HTMLElement and also you can get all attributes and class list of that custom Element to create more powerful and dynamic component:
class mydatepicker extends HTMLElement {
Classes;
CustomLabel;
constructor() {
super();
this.classes = this.classList.value;
this.CustomLabel = this.getAttribute("CustomLabel");
}
connectedCallback() {
this.innerHTML = `
<div class="${this.classes}">
<label> ${this.CustomLabel} </label>
<input type="text" class="txt txtDate"/>
<input type="button" class="btn btnDate" value="Select from Calendar"/>
<span class="remainedDays"></span>
<div>
`;
}
}
customElements.define("my-datepicker", mydatepicker);
.dt1{
color:red;
}
<my-datepicker class="dt1 dt2" CustomLabel="this is custome lable"> </my-datepicker>
Note that you can pass some classes and custom attribute you want

Angular 7 add new fields to form

I have a small form and when the user clicks on an element I want to display some more fields to the form. This action can be done multiple times. So my ideia is to have a separated html file with these fields to be appended to the form so I got this
public showMoreFields(): void {
const wrapper_div = document.getElementById("wrapper");
const template = require("./my-template.html")
container.innerHTML += template
}
The new fields are being appended properly.
My first question is: Is this the best approach to load external html? (I don't have the "text/template" script tag)
Or should I create a new component and append it to the maim form?
....
<input type="text" .... />
<my-new-fields></my-new-fields>
...
<button></button>
If so, how do I append new ones?
Also read about ngTemplateOutlet but didn't figure out how can apply to my case.
I am quite confused about this
Second. Although my new fields are being displayed the click events they are not triggering my functions.
exemple:
<span class="fa fa-remove" (click)="cleanInput()"></span>
// this is not executing the cleanInput function
Thanks
You can use *ngIf or [hidden] attributes on the section which you want to hide.
Example:
<input [(ngModel)] = "model1">
<your-component *ngIf="areExtraFieldsVisible">
</your-component>
<button (click)="showExtraFields()"></button>
1,
you can use flag in your component to show/hide data on button click:
in component:
showData: boolean = false;
in html:
<button (click)="this.showData=!this.showData">show/hide</button>
<div *ngIf="this.showData">
...
</div>

How to adjust width in Nogray timepicker input?

<html>
<head>
<script type="text/javascript" src="js/ng_all.js"></script>
<script type="text/javascript" src="js/ng_ui.js"></script>
<script type="text/javascript" src="js/components/timepicker.js"></script>
<script type="text/javascript">
ng.ready(function() {
var my_timepicker = new ng.TimePicker({
input: 'my_timepicker'
});
});
</script>
<style>
#my_timepicker {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
Time : <br><input id="my_timepicker" name="my_timepicker_input" style="width:10px" type="text" autocomplete="off" required><br><br>
</body>
</html>
This is my html to use Nogray time picker. I can't adjust the width of input. And i have tried to understand source code but it is too difficult for me. Can anyone say another way of doing it?
Actually, nogray timepicker doesn't use the input given in the body. It will create a new input element above it and the input my_timepicker will be hidden. So when we get element by id, it actually points to the my_timepicker input. But when we add a class to my_timepicker input, it will add the same class to the nogray created input also. Therefore when we get element by class, it actually points to the nogray created input.
Nogray timepicker use the input "my_timepicker" only for get the position where they want to create actuall inputs.
input show on the browser is not the input given by you.
You can observe it by clicking inspect element on the input.
However any class added to the user defined input will also added to nogray created input. That's why css worked when you select it by class and not when you select it by id.
Instead of identifying element by id, i have used class attribute to set the width in css. Hence its working well!.

Extracting the input value from a mathjax paper-input polymer object

I am trying to read the value the user inputs into a polymer paper-input object. However, this is a custom object as follows :
<dom-module id="mathjax-input">
<template>
<paper-input on-input="handleInputChanged" label="{{ label }}" value="{{ formula }}">
</paper-input>
</template>
This is intending to show the user input translated (if it's in LaTeX code) to the equivalent LaTeX result. The following is the input box:
<div>
<mathjax-input id="formula" label="Enter formula: " ></mathjax-input>
</div>
Assuming now that the "onsubmit" event of the form calls the following function:
<script>
function copy_latex(){
var input = document.getElementById('formula').value
return true;
}
</script>
variable "input" should now get what the user typed. This is not working though. Can you please help me locate the error?
-Thanks!!
Solved with:
var input = document.querySelector('#formula').formula;
Thanks a lot!

React.js Bootstrap Add or Remove Input Fields

I'm building a web app using React.js and react-bootstrap. I have a form page where the user can type in symptoms of a disease that they are experiencing. I want the user to be able to type in text and also have the option to remove previously typed text.
An example of it being done in Javascript is here:
http://bootsnipp.com/snippets/featured/dynamic-form-fields-add-amp-remove-bs3
I would like to have the same feature as the link above but using React. Here's the code I have so far for the section, but I'm unsure of the best way to continue.
var closeButton = <Button onClick={this.removeSymptomField()}>Close</Button>;
<Input type="text" buttonAfter={closeButton} placeholder="Type a symptom here."/>
<Button onClick={this.addSymptomField()}>Click to add a new symptom.</Button>
When this.addSymptomField() is called, I want to add an Input field to the page, and when this.removeSymptomField() is called, I want to remove the existing Input field from the page.
Thank you so much!
You could keep a list of current inputs in state and modify that when calling addSymptomField and removeSymptomField
In your component constructor
this.state = { inputs: [] }
In render
<div className="inputs">
{this.renderInputs()}
</div>
And your renderInputs method could look like this
renderInputs() {
return this.state.inputs.map((input, index) => <Input key={index} type="text" buttonAfter={closeButton} placeholder="Type a symptom here."/>)
}
Then simply add or remove inputs to/from the list when calling the addSymptomField and removeSymptomField methods

Categories