vue nested event fired but parent one is omited - vue.js

I'm using this library for autocomplete select, and in my logic, I also want to trigger require validation (from vuelidate library) on the fly. I want to trigger the require validation rule when the user focuses out the input and when the user selects some value from the suggestion list.
And for some reason when I'm selecting a value by the first time from the suggestion list it's triggering focusout event not a select, probably b-z list is out of input focus, but when I'm selecting an item from the list by the second time it's triggering select event not focusout (as it should). NOTE: vue trigger select event only when I select value for the second time, first, third and all next times it's always triggering focusout event.
Question: why it's not triggering select event and how to force triggering it??
Code snippet:
<vue-simple-suggest v-model="city.searchInput"
:debounce="300"
:min-length="2"
display-attribute="name"
value-attribute="id"
:list="getCity"
:filter-by-query="true"
#select="citySelect">
<input type="search"
class="form-control"
placeholder="Place of birth"
#focusout="cityError" />
</vue-simple-suggest>
methods: {
cityError() {
console.log('cityError');, // <== when I select some item from suggestions list by the first time this event triggered
},
citySelect() {
console.log('citySelect'); // <== when I'm clicking by input second time (the suggestions list already loaded) and select some (or same) value from suggestions list this event triggered
},
getCity() {
// here should be ajax call, but for now just dummy data
return [{
"id": "691b237b0322f28988f3ce03e321ff72a12167fd",
"name": "Paris",
"lat": -33.8599358,
"lng": 151.2090295
},
{
"id": "691b237b0322f28988f3ce03e321ff72a12167fs",
"name": "New York",
"lat": -33.8599358,
"lng": 151.2090295
},
]
}
}
I open an issue on github https://github.com/KazanExpress/vue-simple-suggest/issues/353 (it has detailed information and small video which showing the issue, you can check browser console), but I'm not sure it's related to the library.
Thanks in advance!

I saw in the documentation of the library that it allows blur event. Could you try #blur in vue-simple-suggest component instead of #focusout in the input?
Otherwise you can run a controller in the #select="checkCitySelection" to avoid the #focusout event in the input:
checkCitySelection(citySelected) {
this.$v.city.value.$touch();
if (this.$v.city.value.$invalid) this.cityError()
else this.citySelect();
}

Related

Vue Google Place Autocomplete-how can I make the selected value display?

I am implementing the component like this:
<place-autocomplete-field
v-model="field"
name="field"
label="Address lookup"
:api-key="api_key.api_key"
placeholder="Start typing here"
#autocomplete-select="onPlaceInput"
>
</place-autocomplete-field>
...
data() {
return {
api_key,
field: null
};
...
While the #autocomplete-select event fires fine, and delivers the selected value, the value displayed in the component's input field does not update on selecting from the place options. All that is in the input field is whatever was typed in there. This is not how it works in the demo on Github. Can anyone spot what I may be doing wrong?

Object reactivity of complex object

I have an issue with complex object reactivity.
I've read everything I can on stack to find a way to solve it, but nothing works. I've looked at object reactvity and array caveats on vuejs, but not working either.
So I'm asking some help please.
Let me explain the project:
I have 2 columns :
- on the left side, I CRUD my content
- on the right side, I display the results
I have my object, and I'm adding new elements on its "blocks" property (text, images, etc...)
[
{
"uid": 1573224607087,
"animation": "animationName",
"background": {
"bckColor": "#ff55ee",
...
},
"blocks": []
}
]
On click event, I add a new element via this method. Everything is ok, I can CRUD a block.
addBloc(el) {
if (el.type == "text") {
const datasA = {
type: "text",
uid: Date.now(),
slideId: this.pagination.currentPage,
content: el.content,
css: {
color: "#373737",
...
},
...
};
this.slides[this.pagination.currentPage].blocks.push(datasA);
this.$bus.$emit("newElement", datasA);
}
To modify the order of my elements on the display side, I added a drag and drop module to move my block on my DOM tree. Smooth dnd
The problem is, when I drang&drop my element, my object is updated correctly, but the DOM isn't. The dragged element goes back to its initial position.
What is strange, when I try to modify my block (the one I dragged), it modifies the other one.
I'me adding a small video, so you can see what's happening.
Small animation to show you what's going on
I add some more explainations.
I use event bus to communicate between my components, and the right side is using its own object!
I don't know how I can solve this issue.
Tell me if you need more information.
Thank you all !
EDIT 1 :
I added an id to each block to see what happens when I start Drag&Drop. ==> blocks are moving correctly. The problem is not coming from the method onDrop() but from my nested components if I understand well. They don't update. I'm going to search for this new issue.
I've added a new gif to show what's going on.
This is the nested structure
TheSidebar.vue => top container
<Container
:data-index="i"
#drop="onDrop(i,$event)"
:get-child-payload="itemIndex => getChildPayload(i, itemIndex)"
lock-axis="y"
>
<Draggable
v-show="pagination.currentPage === i"
v-for="(input, index) in slides[i].blocks"
:key="index.uid"
:id="'slideBlocksContainer'+index"
class="item"
>
blockId #{{input.uid}}
<AppContainer
v-if="input.type == 'text'"
:blocType="input.type"
:placeholder="input.content"
:id="index"
:slideId="i"
></AppContainer>
</Draggable>
</Container>
Then I have my AppContainer.vue file, which is a top level. In this I have the specific elements of each input type
And I have AppElement.vue file, which is common elements, I can use everywhere
Something like this
TheSidebar
--AppContainer
----AppElement
Know I don't know yet, how to force vue to update AppContainer.vue and AppElement.vue
EDIT 2 :
As suggested in this article I've changed the key of the component and now , when I drag and drop my elements, they stay where they are dropped.
What I see also, is that the AppElement inputs, are related to their own AppContainer. So everything is ok now, but I don't know if it is best practices.
The issue appears to be that the Smooth dnd library you are using is not updating the array of blocks that you are passing to it, it is likely making a copy of the array internally. So when you change the position of the blocks by dragging and dropping, you are not changing your blocks array, just the internal copy.
Looking at the Smooth dnd documentation, if you wanted to access the modified array you could try using the drag-end event handler:
onDragEnd (dragResult) {
const { isSource, payload, willAcceptDrop } = dragResult
}

Vue JS 2 - dynamic array

I understand with Vue JS 2, you have to declare reactive properties upfront.
However, just wondering how would you do a rest call if the child objects appear depending on a few other conditions. For example:
"abc": {
"tests": [
{
"a1": "xxxx",
"result": null,
"selected": false,
"comment": null
} ...
]
}
Now in this example, what happens if the tests are empty ((null)) in some circumstances?
eg: if you bind it using the v-model xx.xx.abc.tests[1].selected - This wont work as tests[1] is null.
So I tried using Vue.set in mounted function to assign a default value but that did not work. It will be hard to define all these in a static data as then I have to know all the tests before the rest call.
Looking at the Vue warning when accessing nested object the issue is if I do the check for inside
the checkbox (Checkbox is rendered from Spring MVC tag).
<form:checkbox id="xx" path="..Spring MVC Path.." v-if="(xx.xx.abc.tests!=null && xx.xxx.abc.tests[3].selected)" **v-model**="xx.xxx.abc.tests[3].selected"/>
The checkbox does not appear at all. I want it to appear regardless of empty value as it gives users to add the option. Also, the other option of statically declaring it does not work as I don't know want to hard code and define array.
for example that means in case another element is added it is hardcoded into script:
[
{
"testName": String,
"result": String,
"selected": false,
"comment": String
},
{
"testName": String,
"result": String,
"selected": false,
"comment": String
}
]
Basically I need to bind using v-model even if it is null in this case. Tried Vue.set but for some reason did not appear to work.
I guess I am missing something here,any help would be appreciated.
Assume that you have a list of checkbox to render whether the child element is null on not. but you do know the array length, right?
If you do, consider use v-for to render checkboxes (then you’re able to track array item by index) and listening on its change event then assign specific value to specific object when events fire
thanks for the replies. As this was due to rest call not returning all required attributes that was defined in Vue model(As mentioned in question).So I checked that in final section of rest call and if they are empty, created them.
axios
.get(***URL***)
.then(
response => {
this.info = response.data;
this.status.loaded = true;
}
)
.finally(
() => {
*** check and fill missing attributes with default values ***
**Example: this.$set(this.someObject, 'b', 2)
}
)
Reference:
https://v2.vuejs.org/v2/guide/reactivity.html

Vue return v-model name by method

I'm creating a rates per hour form. I have all the categories in my database rates table. I'd like to be able to grow the categories and it will automatically grow the fields on my form.. loop through it all.
The user needs to select a begin to end rate. I start at this rate and end at this rate.
So right now I have these values in json being loaded onto my page:
rateCategories: [ { "name": "Local", "input1": "Local$0", "input2":
"Local$1" }, { "name": "International", "input1": "International$0",
"input2": "International$1" }, { "name": "Weekdays", "input1":
"Weekdays$0", "input2": "Weekdays$1" }, { "name": "Weekends",
"input1": "Weekends$0", "input2": "Weekends$1" } ]
userRates: { "Local$0": 10, "Local$1": 25, "International$0": 300,
"International$1": 400, "Weekdays$0": 100, "Weekdays$1": 200,
"Weekends$0": 200, "Weekends$1": 300 }
What I'm doing is looping through rateCategories array to create the form. I need to dynamically create the v-model name for all the input fields to match the keys in userRates...
This is where it stops working! It will create the v-model name for me if I write:
:v-model.number="'userRates.'+rateCategories.name+'$0'"
but it won't compute it with the value from the user array. I do get a value into an input field if I write out the v-model name without creating it dynamically like this:
v-model.number="userRates.Weekdays$0"
but then the form needs to be manually updated every time a new category is added.
Is it really impossible to have a dynamic v-model name?? Why??
Also if that's so, how do I go about this so the page can loop through the categories when added to the database and not need a manual update to the page when categories are added or taken away??
Note: I'm also using Vuex store, so I'd rather it not break anything with my getter and setter functions too
Vue.js has full javascript expression support in data bindings, so an object's property can be accessed like you would in plain javascript.
Have you tried using userRates[rateCategories.name$0] ?
Using Javascript Expressions in Vue.js

Does the JIRA REST API require submitting a transition ID when transitioning an issue?

If I POST an issue transition like this:
{
"fields" : {
"resolution" : {
"name" : "Fixed"
}
}
}
...I get this error:
{
"errorMessages" : ["Missing 'transition' identifier"],
"errors" : {}
}
This seems to imply that I need to include a transition ID along with my list of changed fields. https://stackoverflow.com/a/14642966/565869 seems to say the same. Fine.
However, transition IDs appear to be global. It's not enough to look up the highest transition ID for this issue and increment it; such an ID is probably in use elsewhere. At some expense, I could get the highest transaction ID used anywhere in the system; this might be 68,000 at this moment. But if I were then to use transaction ID 68,001 there's a real chance that a GUI user would attempt a transition of their own and use this ID before I could.
I could use transaction IDs in the range of 1,000,001 and up, but if the JIRA web GUI uses the highest previously used transaction ID when generating new IDs I'll just collide in this range instead of the 68,000 range. I could use 69,000 and trust that there won't be a thousand transitions in the length of time it takes to get the highest transaction ID.
These both seem terribly clumsy, however. Is there no way to post a transition and let JIRA generate its own unique ID? I don't need to retrieve the generated IDs, I just want to update issues' statuses and resolutions.
You're getting mixed up a bit. So lets see if I can explain it better for you.
To transition a JIRA Issue, you use the Transition ID to identify what transition to apply to the issue. You aren't specifying an ID for a transaction or a transition ID to identify that the transition occurred, JIRA takes care of this for you.
The easiest way to understand it is to see it.
So first you can look at what transitions are available to an Issue by doing a GET to the API Call:
/rest/api/2/issue/${issueIdOrKey}/transitions
Example:
/rest/api/2/issue/ABC-123/transitions
Which will show something like this:
{
"expand": "transitions",
"transitions": [
{
"id": "161",
"name": "Resolve",
"to": {
"description": "A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.",
"iconUrl": "https://localhost:8080/images/icons/statuses/resolved.png",
"id": "5",
"name": "Resolved",
"self": "https://localhost:8080/rest/api/2/status/5"
}
}
]
}
So you can see only 1 transition is available for issue ABC-123 and it has an ID of 161.
If you were to browse to that JIRA Issue through the GUI, you would see only 1 Transition available and it would match the API Call. In fact if you inspected the element you should see it having an a tag and in the href something like action=161
So should you want to transition this issue, you'll need to do a POST to the following URL:
/rest/api/2/issue/ABC-123/transitions
With JSON like this:
{
"update": {
"comment": [
{
"add": {
"body": "Bug has been fixed."
}
}
]
},
"fields": {
"assignee": {
"name": "bob"
},
"resolution": {
"name": "Fixed"
}
},
"transition": {
"id": "161"
}
}
Which uses the transition ID found from the call that shows all transitions. I also update the resolution and assignee and add comments at the same time.
That make a bit more sense?