Ember could not get select value from template to component - select

I'm struggling with this. I would like to pass a select value from template to component.
Here is my template
<select name="bank" class="form-control" id="sel1" onchange={{action "updateValue" value="bank"}}>
{{#each banks as |bank|}}
<option value={{bank.id}}>{{bank.name}}</option>
{{/each}}
{{log bank.id}}
</select>
And here is my component
import Ember from 'ember';
export default Ember.Component.extend({
store: Ember.inject.service('store'),
banks: Ember.computed(function() {
return this.get('store').findAll('bank');
}),
didUpdate() {
const banques = this.get('banks');
const hash = [];
banques.forEach(function(banque) {
hash.push(banque.get('name'));
});
Ember.$(".typeahead_2").typeahead({ source: hash });
},
actions: {
expand: function() {
Ember.$('.custom-hide').attr('style', 'display: block');
Ember.$('.custom-display').attr('style', 'display: none');
},
updateValue(selectedValue) {
this.set('bank.id', selectedValue);
},
login() {
console.log(this.get('bank.id'));
}
}
});
And i've got this beautiful error : Property set failed: object in path "bank" could not be found or was destroyed.
Any idea ? Thanks

When you use value attribute then you need to specify correct property name to be retrieved from the first argument(event). in your case you just mentioned bank - which was not found in event object. that's the reason for that error.
onchange={{action "updateValue" value="target.value"}}
inside component
updateValue(selectedValue) {
this.set('bank.id', selectedValue);
},

Related

Bootstrap-vue modal manipulate ok-disabled state in function

I've set the default OK Button in a Bootstrap-Vue Modal to disabled true and want to change it when inputing something in ab-form-input. Calling the function works but disabling ok-disabled not. Can't get access to the property. Seems to be a very basic question but in the component docs in bootstrap-vue there is only the infor that state can be changed (true-false) but not how to manipulate via script.
`
<template>
<b-modal
id="component-modal"
title="Add Component"
#ok="handleOk"
:ok-disabled="true"
>
<div class="container">
<b-row>
<b-col>Component: </b-col>
<b-col>
<b-form-input
v-model="component"
id="new-component"
required
#input="enableOK"
></b-form-input>
</b-col>
</b-row>
</div>
</b-modal>
</template>
<script>
import axios from 'axios';
import store from '../../store';
export default {
data() {
return {
count: 0,
};
},
methods: {
handleOk() {
this.handleSubmit();
},
handleSubmit() {
this.insertComponentClass(this.component, store.state.project);
delete this.component;
},
insertComponentClass(componentClass, pid) {
const path = `${store.state.apiURL}/componentclass/add`;
const payload = {
name: componentClass,
project_id: pid,
};
axios
.put(path, payload)
.then(() => {
this.$parent.getComponents();
})
.catch((error) => {
console.error(error);
});
},
enableOK() {
console.info('enable ok fired');
this.ok-disable = false; // doesnt wor, linter says "Invalid left-hand side in assignment expression"
},
},
};
</script>
`
There's a few things going on here that are incorrect.
You're binding the ok-disabled prop to a hardcoded value of true in your template. If you want that value to change, you'll need to bind it to a variable that you can update in your components <script>
For example, you can update the modal's :ok-disabled prop to:
:ok-disabled="okDisabled"
Then in your <script> data function, add it to the return object (defaulted to true):
data() {
return {
count: 0,
okDisabled: true,
}
}
Now the modal's :ok-disabled property is bound to that variable and we can change the value in the enableOk method like so:
this.okDisabled = false;
Note regarding the lint error, the name of the variable you're trying to assign to this.ok-disable is not a valid variable name. You can't use a dash (-) character for a Javascript variable name. You can rename it to the property we created earlier this.okDisabled

Magneto 2- remove default checkbox for same shipping and billing address

As there are alot of question regarding same and also have verified answers too, but it not solving my issue as ,I want to remove default check from that from on checkout page , I am using Amasty one page checkout
Any help will be appreciated.
Thank you
My Magento Version is 2.4
instead of overriding core js file I use Js Mixin way for achieve output see below image.
create Vendor\Module\view\frontend\web\js\view\checkout\billing-address-mixin.js
define([
'jquery',
'ko',
'underscore',
'uiRegistry',
'Magento_Checkout/js/model/quote',
], function (
$,
ko,
_,
registry,
quote,
) {
'use strict';
var mixin = {
/**
* on change billing address set `isAddressSameAsShipping` variable as a "false" for display Edit Button below the Address
*
* see /Magento_Checkout/view/frontend/web/template/billing-address/details.html template file
*/
initObservable: function () {
var result = this._super();
quote.billingAddress.subscribe(function (newAddress) {
this.isAddressSameAsShipping(false);
}, this);
return result;
},
/**
* return false for hide the `My billing and shipping address are the same` checkbox
*
* see /Magento_Checkout/view/frontend/web/template/billing-address.html template file
*/
canUseShippingAddress: ko.computed(function () {
return false;
}),
}
return function (target) {
return target.extend(mixin);
};
});
& then create Vendor\Module\view\frontend\requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Checkout/js/view/billing-address': {
'Vendor_Module/js/view/checkout/billing-address-mixin': true
},
}
},
}
OUTPUT:-
Overwrite:
vendor/magento/module-checkout/view/frontend/web/template/billing-address.html
in your custom theme:
app/design/frontend///Magento_Checkout/web/template/billing-address.html
And remove:
<div class="billing-address-same-as-shipping-block field choice" data-bind="visible: canUseShippingAddress()">
<input type="checkbox" name="billing-address-same-as-shipping"
data-bind="checked: isAddressSameAsShipping, click: useShippingAddress, attr: {id: 'billing-address-same-as-shipping-' + getCode($parent)}"/>
<label data-bind="attr: {for: 'billing-address-same-as-shipping-' + getCode($parent)}"><span
data-bind="i18n: 'My billing and shipping address are the same'"></span></label>
</div>

Vue.js: How to fill a form prepopulated with data from a get request?

I want to load data with a GET request and fill the data to the input data attributes at vue.js 3 like
<input id="name" type="text" v-bind:placeholder="$t('message.NamePlaceholder')" value="{{ name }}" required>
and this is my script part
<script>
export default {
data () {
return {
userInformation: {},
name: "",
}
},
mounted () {
this.getUserInformation();
},
methods () {
getUserInformation() {
this.$axios({
method: 'get',
url: 'http://127.0.0.1:8000/api/get_user_information',
}).then(response => {this.userInformation = response.data});
this.name = this.userInformation.Name;
}
},
}
But the input field contains only {{ name }}. I tried also v-bind:value, but this didn't solve the problem.
Whenever you need to bind values to attributes {{}} are unnecessary. You can just write v-bind:value="name" or :value="name"
E.g.:
<input id="name" type="text" :placeholder="message.NamePlaceholder" :value="name" required></input>
The mistake was that I have to set the variable this.name at the axios command:
this.$axios({
method: 'get',
url: 'http://127.0.0.1:8000/api/get_user_information',
}).then(response => {
this.userInformation = response.data;
this.name = this.userInformation.Name;
});

Bootstrap-vue: Auto-select first hardcoded <option> in <b-form-select>

I'm using b-form-select with server-side generated option tags:
<b-form-select :state="errors.has('type') ? false : null"
v-model="type"
v-validate="'required'"
name="type"
plain>
<option value="note" >Note</option>
<option value="reminder" >Reminder</option>
</b-form-select>
When no data is set for this field I want to auto-select the first option in the list.
Is this possible? I have not found how to access the component's options from within my Vue instance.
your v-model should have the value of the first option.
example
<template>
<div>
<b-form-select v-model="selected" :options="options" />
<div class="mt-3">Selected: <strong>{{ selected }}</strong></div>
</div>
</template>
<script>
export default {
data() {
return {
selected: 'a',
options: [
{ value: null, text: 'Please select an option' },
{ value: 'a', text: 'This is First option' },
{ value: 'b', text: 'Selected Option' },
{ value: { C: '3PO' }, text: 'This is an option with object value' },
{ value: 'd', text: 'This one is disabled', disabled: true }
]
}
}
}
</script>
You can trigger this.selected=${firstOptionValue} when no data is set.
what if we don't know what the first option is. The list is generated?
if you have dynamic data, something like this will work.
<template>
<div>
<b-form-select v-model="selected" :options="options" />
<div class="mt-3">Selected: <strong>{{ selected }}</strong></div>
</div>
</template>
<script>
export default {
data() {
return {
selected: [],
options: [],
};
},
mounted: function() {
this.getOptions();
},
methods: {
getOptions() {
//Your logic goes here for data fetch from API
const options = res.data;
this.options = res.data;
this.selected = options[0].fieldName; // Assigns first index of Options to model
return options;
},
},
};
</script>
If your options are stored in a property which is loaded dynamically:
computed property
async computed (using AsyncComputed plugin)
through props, which may change
Then you can #Watch the property to set the first option.
That way the behavior of selecting the first item is separated from data-loading and your code is more understandable.
Example using Typescript and #AsyncComputed
export default class PersonComponent extends Vue {
selectedPersonId: string = undefined;
// ...
// Example method that loads persons data from API
#AsyncComputed()
async persons(): Promise<Person[]> {
return await apiClient.persons.getAll();
}
// Computed property that transforms api data to option list
get personSelectOptions() {
const persons = this.persons as Person[];
return persons.map((person) => ({
text: person.name,
value: person.id
}));
}
// Select the first person in the options list whenever the options change
#Watch('personSelectOptions')
automaticallySelectFirstPerson(persons: {value: string}[]) {
this.selectedPersonId = persons[0].value;
}
}

Properties won't update on input change

I'm trying to adapt a working form I found for polymer 1.0 in order to work on polymer 2.0 but these two way data bindings don't seem to work.
My template:
<paper-input>
<label>Username</label>
<iron-input bind-value={{formData.username}}><input id="username" type="text" value="{{formData::input}}"></iron-input>
</paper-input>
<paper-input>
<label>Password</label>
<iron-input bind-value={{formData.password}}><input id="password" type="password" value="{{formData::input}}"></iron-input>
</paper-input>
<div class="wrapper-btns">
<paper-button raised class="primary" on-tap="postLogin">Log In</paper-button>
<paper-button class="link" on-tap="postRegister">Sign Up</paper-button>
</div>
My actions:
class MyLogin extends Polymer.Element {
static get is() { return 'my-login'; }
static get properties() {
return {
storedUser: Object,
error: String,
formData: {
type: Object,
value: {},
},
}
}
_setReqBody() {
console.log(this.formData) // <--- THIS LINE!
this.$.registerLoginAjax.body = this.formData;
}
postLogin() {
this.$.registerLoginAjax.url = 'http://localhost:3001/sessions/create';
this._setReqBody();
this.$.registerLoginAjax.generateRequest();
}
}
The indicate line will always print undefined though. What am I doing wrong?
Here's the full code: https://github.com/lpfjustino/PolymerQuickstart/blob/master/web/src/my-login.html
And here's the code mine is based on:
https://auth0.com/blog/build-your-first-app-with-polymer-and-web-components/
paper-input doesn't need any label nor iron-input inside it by default. That only goes for paper-input-container. So the following would be okay
<paper-input label="Username" value="{{formData.username}}"></paper-input>
However if you insist on using paper-input-container instead, then
<paper-input-container>
<label slot="label">Username</label>
<iron-input bind-value="{{formData.username}}" slot="input">
<!-- You don't need to add two-way binding for your input element here
since `iron-input` already handles that for you using its `bind-value`
attribute. -->
<input />
</iron-input>
</paper-input-container>
Also, when you declare an Object property, you should initialize it using a function to insure that each element instance would have its own copy of the property.
static get properties() {
return {
...
formData: {
type: Object,
value: function() {
return {}; // or return { username: '', password: '' }
},
},
};
}