I have the following code which should loop over an array to populate an HTML select element but getting zero data?
<div class="w-full" x-data="{classes: [
{
room: 'online',
id: 1,
},
{
room: 'in class',
id: 2,
}
]}">
<select name="" id="">
<template x-for="class in classes" :key="class.id">
<option x-text="class.room" :value="class.room"></option>
</template>
</select>
</div>
Please check this. I renamed class to cls (may be class word is conflicting though did not see any error in concole)
https://codepen.io/rajdeepdebnath/pen/MWyNoKj?editors=1010
<div class="w-full" x-data="{classes: [
{
room: 'online',
id: 1,
},
{
room: 'in class',
id: 2,
}
]}">
<select name="" id="">
<template x-for="cls in classes" :key="cls.id">
<option x-text="cls.room" :value="cls.room"></option>
</template>
</select>
</div>
Related
I have an alpineJS component that data inside of init() function.
Inside of this component, I am adding the item component dynamically. Dynamically added item property is working fine. But how can I sum all item-total values and get them into my sub_total field? sample code attached below.
I have tried the update() function onkeyup of the item price and quantity change.
But not working.
<div x-data="init()">
<div x-data="item()">
<input type="text" name="price" id="price" x-model="price" x-on:keyup="update()">
<input type="text" name="qty" id="qty" x-model="qty" x-on:keyup="update()">
<input type="text" class="item-total" name="total" id="total" x-model="total()">
</div>
<div x-data="item()">
<input type="text" name="price" id="price" x-model="price" x-on:keyup="update()">
<input type="text" name="qty" id="qty" x-model="qty" x-on:keyup="update()">
<input type="text" class="item-total" name="total" id="total" x-model="total()">
</div>
<input type="text" name="sub_total" id="sub_total" x-model="sub_total">
<input type="text" name="vat" id="vat" x-model="vat">
<input type="text" name="total" id="total" x-model="total()">
<div>
<script>
function update() {
let sub_total = 0;
document.querySelectorAll(".item-total").forEach(function(el) {
sub_total += parseFloat(el.value);
});
console.log(sub_total);
document.getElementById("sub_total").value = sub_total;
return sub_total;
}
function item() {
price: 0,
qty: 0,
total() {
return this.price * this.qty;
}
}
function init() {
sub_total: 0,
tax: 0,
total() {
return this.sub_total + this.tax;
}
}
</script>
I would suggest using an object inside your outer AlpineJS component instead of nesting components. Communication across components is a little tricky and can be done best via custom events, but in your case I don't see why that's even needed.
Here is a quick and dirty working example of what I would probably try:
window.table = function() {
return {
items: [
{ price: 0, qty: 1, total: 0 },
{ price: 0, qty: 1, total: 0 },
],
vat: 0,
sub_total: 0,
total() {
return this.items.reduce((carry, val) => carry + Number(val.total), 0);
},
subtotal() {
return this.items.reduce((carry, val) => carry + Number(val.price), 0);
},
}
}
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.x.x/dist/alpine.min.js"></script>
<div x-data="table()">
<template x-for="item in items">
<div>
<input type="text" name="price" x-model="item.price" #input="item.total = item.price * item.qty">
<input type="text" name="qty" x-model="item.qty" #input="item.total = item.price * item.qty">
<input type="text" class="item-total" name="total" x-model="item.total">
</div>
</template>
<input type="text" name="sub_total" id="sub_total" :value="subtotal()" readonly>
<input type="text" name="vat" id="vat" x-model="vat">
<input type="text" name="total" id="total" :value="total()" readonly>
</div>
I left your vat model in but don't do anything with it, as I don't see that you have the taxes implemented yet. But the working example should be a good starting point for you.
Please note that your id attributes should be unique. You should not have multiple inputs with id="price" etc. in your document. Also you have not initialized the Alpine component JS correctly, the function should return an object, you have been throwing your code right into the function, which will cause errors.
I want to populate stored images from database to fill dropdown the images are in airline_images folder the image path is stored in database i want user when click on the airlines dropdown it will show the stored airliens with its images
here is the blade code :
<div class="form-group col-md-2">
<label>#lang('site.airline')</label>
<select class="form-control select2 status-type" style="width: 100%;"
name="airline"
id="airline">
#foreach ($airlines as $airline)
<option value="{{ $airline->code }}">{{ $airline->name }} <img src="{{ $airline->image_path }}" style="width: 100px" class="img-thumbnail" alt="">
</option>
#endforeach
</select>
</div>
You may consider using 3rd party jQuery library like ddSlick
Usage
$('select#airline').ddslick({
data: ddData,
width: '100%',
imagePosition: "left",
selectText: "Select your favorite airline",
onSelected: function (data) {
console.log(data);
}
});
PS : The plugin requires specific data format
var ddData = [
{
text: "Tunisair",
value: 1,
selected: false,
description: "Description goes here",
imageSrc: "http://path_to_img"
},
{
text: "Turkish airlines",
value: 2,
selected: true,
description: "Description goes here",
imageSrc: "http://path_to_img"
},
{
text: "Lufthansa",
value: 3,
selected: false,
description: "Description goes here",
imageSrc: "http://path_to_img"
},
//...
];
I am trying to set option selected where option value is 1. But I am getting in trouble when using v-select from vuejs. This is how I am trying to do -
<v-select name="branchid" v-model="branchid"
:options="branches.map(branches => ({label: branches.label, value: branches.value}))"
:selected="branches.value === 1"></v-select>
Would someone help me please to get the option value selected when option value is 1?
I've put together a simplified version of what (I think) you're trying to do:
<template>
<div>
<div>
<select v-on:change="select($event);" value="branchid">
<option disabled value="">Please select one</option>
<option :selected="branchid === 1">1</option>
<option :selected="branchid === 2">2</option>
<option :selected="branchid === 3">3</option>
</select>
<span>Selected: {{ branchid }}</span>
<button v-on:click="selectOne">Select Option 1</button>
</div>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
branchid: 0,
branchidTwo: 1
};
},
methods: {
select: function(evt) {
this.branchid = evt.target.value;
},
selectOne: function() {
this.branchid = 1;
}
}
};
</script>
This does not use the v-model pattern. The docs explicitly state that if you use v-model, the class itself will be used as the source of truth rather than value or selected. You'll see I've added a button that will set the selected option on the select component.
Hope that helps.
Initialize it with select v-model with the value you want selected
new Vue({
el: '#example',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="example">
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
Source : https://v2.vuejs.org/v2/guide/forms.html#Select
I have two components. Component 1:
<template>
<div>
<div class="form-group">
<label for="group">Category</label>
<select name="category" v-model="category" #change="setCategory(category)" class="form-control select-group" id="category">
<option value="1">Category 1</option>
<option value="2">Category 2</option>
</select>
</div>
<tags-multiselect :categoryId="category"></tags-multiselect>
</div>
</template>
<script>
export default {
data () {
return {
category: 1,
}
},
methods: {
setCategory(selected) {
this.category = selected;
},
},
}
</script>
Component 2:
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card card-default">
<div class="card-header">Example Component</div>
<div class="card-body">
I'm an example component.
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['categoryId'],
data () {
return {
category_ids: this.categoryId
}
},
created() {
axios.post('/tags', { category_id: this.categoryId })
.then((response) => {
//
})
.catch((err) => {
})
}
}
</script>
When I select option from first component, I not update category_id on second component with other id I get only 1 id. And when I send axios request with category_id I send always only first param 1. How I can resolve this? How I can refresh the second component with new selected data from select field?
props need to be kebab case in the template.
Try <tags-multiselect :category-id="category"></tags-multiselect>
Also, you don't need to redefine props in the data. Get rid of category_ids in component 2, it will just confuse things.
Then, Vue makes it very easy to extract your state from your components. Shared state (categoryId) and operations on shared state ( axios.post(...) ) would be much happier in global scope, according to me !
I am trying to update the items in my dropdown as my state updates with players BUT I am failing. Please help.
In the child component I have dropdown in the Skylight dialog box.
I am using following code which prints the dropdown of the array of players from the state. State is updated from the json.php (remote server).
<select name="bowlerId" value={this.state.bowlerId} onChange={this.handleInputChange} className="form-control">
<option value="">Select an existing bowler</option>
{
this.currState.teamBowling.players.map(function (player, index) {
return <option value="{player}" key={index}>{player}</option>
})
}
</select>
I can clearly see in the console.log that the state is correctly updated and it prints 11 player names. But in the child component it does not update the dropdown.
Surprising enough, in the child component componentWillReceiveProps() does print new player names as they become availble but the dropdown is not updated still.
Please advise.
Console.log output as page loads
BowlingSummary render() Object {id: 0, name: "", runs: 0, overs: 0, balls: 0…}
PropStore Object {id: 0, name: "", runs: 0, overs: 0, balls: 0…}
BowlingAddBowler render() []
Console.log output after few seconds as data is fetched from php
BowlingSummary render() Object {id: 20, name: "Team Bowling", runs: 0, overs: 0, balls: 0…}
componentWillReceiveProps Object {id: 20, name: "Team Bowling", runs: 0, overs: 0, balls: 0…}
BowlingAddBowler render() []
Parent component named BowlingSummary
class BowlingSummary extends Component {
render() {
const { store } = this.context;
const currState = store.getState();
this.isBowlerBowling = false;
console.log('BowlingSummary render()', currState.teamBowling);
return (
<div>
<div className="score-summary-bar">
<div className="row">
<div className="col-xs-4">Bowling</div>
<div className="col-xs-1"></div>
<div className="col-xs-1">Ovr</div>
<div className="col-xs-1">Mdn</div>
<div className="col-xs-1">Run</div>
<div className="col-xs-1">Wkt</div>
<div className="col-xs-1">Econ</div>
<div className="col-xs-1">W</div>
<div className="col-xs-1">N</div>
</div>
</div>
<div className="score-summary-bowling">
<div className="">
{
currState.teamBowling.players.map(function (player, index) {
if ( player.isBowling === true ) {
this.isBowlerBowling = true;
return <BowlingBowler player={player} key={index}/>
}
})
}
</div>
<div className="">
{
this.isBowlerBowling != true &&
<BowlingAddBowler propStore={store} />
}
</div>
</div>
<div className="score-summary-bowling">
<ScoreThisOver />
</div>
</div>
);
}
}
BowlingSummary.contextTypes = {
store: PropTypes.object
}
export default BowlingSummary;
Child component named BowlingAddBowler
class BowlingAddBowler extends Component {
constructor(props, context) {
super(props, context);
// Setup current state
this.currState = this.props.propStore.getState();
console.log('PropStore', this.currState.teamBowling);
// This component state
this.state = {
bowlerId: 0,
bowlerName: '',
markPrevOverFinished: false
};
// Setup variables
this.players = this.props.players;
// Bind this (so that we write short code in the onChange like onChange=this.func)
this.handleInputChange = this.handleInputChange.bind(this);
}
componentWillReceiveProps(nextProps, nextState){
//this.props.something // old value
//nextProps.something // new value
console.log('componentWillReceiveProps', nextProps.propStore.getState().teamBowling);
}
render() {
//console.log('BowlingBowler render()', this.props);
var responsiveWidth = {
width: '90vw',
transform: 'translate(-23%, 0%)'
};
console.log('BowlingAddBowler render()', this.currState.teamBowling.players);
return (
<div className="row">
<div className="col-xs-12">
<button className="btn" onClick={() => this.refs.dialogAddBowler.show()}>No Bowler Selected. Click To Select</button>
</div>
<SkyLight dialogStyles={responsiveWidth} hideOnOverlayClicked ref="dialogAddBowler" title="Select a new bowler">
<div>
<form onSubmit={this.handleSubmit.bind(this)}>
<label className="bg-yellow">
Total <span className="text-red">0</span> for the loss of <span className="text-red">0</span> wickets in <span className="text-red">0</span> overs
</label>
<div className="spacer-horizontal"></div>
<label>Who will bowl the next over ?</label>
<select name="bowlerId" value={this.state.bowlerId} onChange={this.handleInputChange} className="form-control">
<option value="">Select an existing bowler</option>
{
this.currState.teamBowling.players.map(function (player, index) {
return <option value="{player}" key={index}>{player}</option>
})
}
</select>
<div className="spacer-horizontal"></div>
<b>- OR -</b>
<input type="text" name="bowlerName" value={this.state.bowlerName} onChange={this.handleInputChange} className="form-control" />
<div className="spacer-horizontal"></div>
<input type="checkbox" name="markPrevOverFinished" checked={this.state.markPrevOverFinished} onChange={this.handleInputChange}/>
<label> Mark previous over finished</label>
<div className="spacer-horizontal"></div>
<div className="HorizLine"></div>
<div className="text-right">
<button type="submit" className="btn btn-primary"> Save </button>
</div>
</form>
</div>
</SkyLight>
</div>
)
}
}
This code:
this.currState = this.props.propStore.getState();
is in BowlingAddBowler's constructor and only runs first time when the class is instantiated. You can put it in componentWillReceiveProps of BowlingAddBowler too so that it runs when new data comes from server and parent component updates BowlingAddBowler.