How do you change a class when a button is clicked in Svelte?
The code is here:
<script lang="ts">
let rank = 1;
const changeRank = () => {
if (rank == 1) {
rank = 2
} else {
rank = 1
}
};
</script>
<main>
<div class="card" class:input-focus={rank === 1? "rank-1" : "rank-2"} />
<button on:click={changeRank}>Change Rank</button>
</main>
You are using a class directive (class:...), this will add the class after the : if the value is truthy. This is probably not what you want here, because both values are truthy so it will always add the class input-focus.
You probably meant to do something like this:
<div class="card {rank === 1 ? 'rank-1' : 'rank-2'}" />
If all classes have that prefix you could just do this as well:
<div class="card rank-{rank}" />
Related
I try to return the part of html depending on variable type I want to do like:
<template>
<div>{{getvalue(this.$store.state.output)}}</div>
</template>
<script>
export default {
methods:{
getvalue(output){
if(output.constructor == Array){
re="";
for(i in output){
re+=<p>{{i}}</p>;
}
return re;
}
else if(output.constructor == Object){
re="";
for(i in output){
re+=<p><span>i</span><span>{{output[i]}}</span></p>
}
return re;
}else if(output.constructor == String){
return <p>{{output}}</p>
}
}
},
...
}
</script>
I know in react I can use virtualDOM to do that, how should I do the similar things like above in Vue2.5.11?
#ceejayoz is right. It would be missing the whole point of Vue.
Another mistake is that computed values don't accept parameters. It is supposed to be treated as a value and not a function.
This is a more proper way of doing things in Vue. By using v-if and v-for.
<template>
<div>
<div v-if="getOutputConstructor==Array">
<p v-for="i in this.$store.state.output" :key="i">{{i}}</p>
</div>
<div v-else-if="getOutputConstructor==Object">
...
</div>
<div v-else-if="getOutputConstructor==String">
...
</div>
</div>
</template>
<script>
export default {
computed: {
getOutputConstructor() {
const output = this.$store.state.output;
return output.constructor;
}
}
};
</script>
But.. if you really really want to do it the wrong way, use v-html
I'm quite new to Angular, and I've already searched the web, without finding a correct solution for my situation.
I have a dynamic form created by a *ngFor. I need to disabled the submit button if the inputs are all empty and show the alert div; but I need to enable the submit if at least one of those forms contains something different from ''.
Here is my html code
<form class="form-inline" #form="ngForm">
<div class="form-group" *ngFor="let meta of state.metaById; let i = index" style="margin: 5px">
<label>{{meta.nome}}</label>
<input type="text" class="form-control" #nome (blur)="inputInArray(nome.value, i);">
</div>
<button type="button" class="btn btn-primary" (click)="getCustomUnitaDocumentaliRow(this.param)" [disabled]="fieldNotCompiled">invia</button>
</form>
<div class="alert-notification" [hidden]="!fieldNotCompiled">
<div class="alert alert-danger">
<strong>Va compilato almeno un campo.</strong>
</div>
</div>
and here is my Typescript code
inputInArray(nome: string, indice) {
if (this.state.controlloMetaId = true) {
this.state.metadatoForm[indice] = nome;
}
// this.fieldNotCompiled = false;
for (const i in this.state.metaById) {
console.log(this.state.metadatoForm);
if (isUndefined(this.state.metadatoForm[i]) || this.state.metadatoForm[i] === '') {
this.fieldNotCompiled = true && this.fieldNotCompiled;
} else {
this.fieldNotCompiled = false && this.fieldNotCompiled;
}
console.log(this.fieldNotCompiled);
}
With this code I can check the first time a user type something in one input, but it fails if it empty one of them (or all of them)
Thanks for your time
UPDATE
Check if any input got a change that is different from empty or space, just by doing:
<input ... #nome (input)="fieldNotCompiled = !nome.value.trim()" ....>
DEMO
You can set a listener to the form changes:
#ViewChild('form') myForm: NgForm;
....
ngOnInit() {
this.myForm.valueChanges.subscribe((value: any) => {
console.log("One of the inputs has changed");
});
}
I have created a React component using redux-form and am looking to autoFocus on the first field. The fields are created by looping through an object and creating a field for each item in that object. When I use autoFocus in the JSX is autoFocuses on the last field in the form (which makes sense).
Does anyone know how I can autoFocus on the first field in the form?
Here is my component:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
class BalanceForm extends Component {
constructor(props) {
super(props);
this.submitForm = this.submitForm.bind(this);
this.cancel = this.cancel.bind(this);
}
cancel() {
//not relevant
}
submitForm(e, values) {
//not relevant
}
render() {
return (
<div>
{this.props.balanceFormVisible &&
<div className="modal-background">
<div className="modal">
<form onSubmit={this.submitForm}>
{Object.keys(this.props.accounts).map((key) => {
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
autoFocus
/>
</div>
)
})}
<button type="submit">Submit</button>
<button onClick={ this.cancel } className="cancelbtn" >Cancel</button>
</form>
</div>
</div>
}
</div>
);
}
}
BalanceForm = reduxForm({form: 'balance'})(BalanceForm)
export default BalanceForm;
Thanks in advance :)
Solution to this was to conditionally render the form field. Thanks to Alexander Borodin for the inspiration...
{Object.keys(this.props.accounts).map((key, i) => {
console.log(key, i)
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
{(i === 0) ? (
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
autoFocus
/>
) : (
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
/>
)}
</div>
)
})}
Some of these either didn't compile or are a bit verbose. This worked for me:
{Object.keys(item)
.map((key, i) =>
<div className={`form-row ${key}`} key={key}>
<label>{key}</label>
<input value={item[key]}
type='text'
onChange={e => {
this._updateValue(key, e.target.value);
}}
autoFocus={i === 0}
/>
</div>
)}
Alternatively, if you hook in to ComponentDidMount, you can ask the DOM to focus the first existing field within the form.
Add a ref to the form
<form onSubmit={this.submitForm} ref='form'>
Use the ref to focus the element after mounting
componentDidMount() {
const firstInput = this.refs.form.querySelector('input')[0];
firstInput && firstInput.focus();
}
Try this:
{Object.keys(this.props.accounts).map((key, i) => {
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
{ (i === 0) ? 'autoFocus': ''}
/>
</div>
)
})}
I ran into an issue where autoFocus wasn't properly passing down from Field to the underlying component. Had to explicitly pass autoFocus in the props prop for Field.
I have a form in a react component that has two change handlers, one for my two draftjs textareas, and one for my other text inputs:
onChangeEditor = (editorStateKey) => (editorState) => {
this.setState({ [editorStateKey]: editorState });
}
handleInputChange(event) {
event.preventDefault();
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
In my render method I have two views that I switch between depending on which view mode I am in, read or edit:
render () {
const Editable = () => (
<div className="editor">
<form className="editor-inner">
<h3>Redigerar: Anbudsbrev</h3>
<h4>Rubrik</h4>
<input type="text" key="text01" name="title" defaultValue={this.state.title} onBlur={this.handleInputChange} />
<h4>Text 1</h4>
<RichEditor editorState={this.state.editorState1} onChange={this.onChangeEditor('editorState1')} name="text01"/>
<h4>Citat</h4>
<input type="text" key="text02" name="quote01" defaultValue={this.state.quote01} onBlur={this.handleInputChange} />
<h4>Text 2</h4>
<RichEditor editorState={this.state.editorState2} onChange={this.onChangeEditor('editorState2')} name="text02" />
<EditorFooter {...this.props} submitForm={this.saveForm} />
</form>
</div>
);
const Readable = () => (
<div>
<h1 className="header66">{this.state.title}</h1>
<div className="text66">{this.state.text01}</div>
<div className="quote100">{this.state.quote01}</div>
<div className="text66">{this.state.text02}</div>
</div>
);
return (
<div>
{ this.props.isInEditMode ? <Editable /> : <Readable /> }
</div>
);
}
When I switch between inputs in my browser I have to click twice in order to get the focus on the right input.
I suspect that this is because a change is triggered on the "blur" event of each input, causing the form to rerender because state is changed. And when the form rerenders, it goes through the { this.props.isInEditMode ? <Editable /> : <Readable /> } which causes the input to lose focus.
The problem is that I don't know how to get around this.
I solved it myself.
It turns out that it was not a good idea to place the Editable and Readable inside of my component as I did. Instead I moved them out to their own components, and it works properly now.
class Editable extends React.Component {
render() {
return (
<div className="editor">
<form className="editor-inner">
<h3>Redigerar: Anbudsbrev</h3>
<h4>Rubrik</h4>
<input type="text" name="title" defaultValue={this.props.title} onChange={this.props.handleInputChange} />
<h4>Text 1</h4>
<RichEditor editorState={this.props.editorState1} onChange={this.props.onChangeEditor('editorState1')} name="text01" />
<h4>Citat</h4>
<input type="text" name="quote01" defaultValue={this.props.quote01} onChange={this.props.handleInputChange} />
<h4>Text 2</h4>
<RichEditor editorState={this.props.editorState2} onChange={this.props.onChangeEditor('editorState2')} name="text02" />
<EditorFooter {...this.props} submitForm={this.props.saveForm} />
</form>
</div>
);
}
};
class Readable extends React.Component {
render() {
return (
<div>
<h1 className="header66">{this.props.title}</h1>
<div className="text66">{this.props.text01}</div>
<div className="quote100">{this.props.quote01}</div>
<div className="text66">{this.props.text02}</div>
</div>
);
}
};
I have a series of divs which are displayed as an -ms-grid. These are outputted using the WinJS.UI.Repeater object.
I need to assign the -ms-grid-row value for the current iteration dynamically.
How would I go about doing this?
Repeater
<div data-win-control="WinJS.UI.Repeater" data-win-options="{template: select('.template')}">
</div>
Repeater Template
<div class="template" data-win-control="WinJS.Binding.Template">
<div class="col1" style="-ms-grid-row:"></div>
<div class="col2" style="-ms-grid-row:"></div>
<div class="col3" style="-ms-grid-row:"></div>
<div class="col4" style="-ms-grid-row:"></div>
</div>
CSS
.grid {
display: -ms-grid;
-ms-grid-columns: (1fr)[4];
-ms-grid-rows: (auto)[1000];
}
.grid .col1 {
-ms-grid-column: 1;
}
.grid .col2 {
-ms-grid-column: 2;
}
.grid .col3 {
-ms-grid-column: 3;
}
.grid .col4 {
-ms-grid-column: 4;
}
Because there could be up to 1000 rows, I need to assign the style inline like this:
Rendered Markup
<div class="col1" style="-ms-grid-row: 1">test</div>
<div class="col2" style="-ms-grid-row: 1">test</div>
<div class="col3" style="-ms-grid-row: 1">test</div>
<div class="col4" style="-ms-grid-row: 1">test</div>
<div class="col1" style="-ms-grid-row: 2">test</div>
<div class="col2" style="-ms-grid-row: 2">test</div>
<div class="col3" style="-ms-grid-row: 2">test</div>
<div class="col4" style="-ms-grid-row: 2">test</div>
But I have no idea how to do this inside the repeater?
Many thanks
Chris
You could try using a converter function like explained here:
http://msdn.microsoft.com/en-us/library/windows/apps/br229809.aspx
for example you can assign a function to the colour of a span and calculate that colour in a function:
<span id="loginName"
data-win-bind="innerText: name; style.color: userType LoginData.userTypeToColor">
</span>
...
WinJS.Binding.processAll(document.getElementById("loginDisplay"), LoginData.login);
WinJS.Namespace.define("LoginData", {
//Data Object
login : { name: "myname", id: "12345678", userType: "admin" },
//Converter function
userTypeToColor: WinJS.Binding.converter(function (type) {
return type == "admin" ? "Green" : "Red";
})
});
I did not test this code with the -ms-grid-row property, but it is worth a try.