I cannot get a select (drop-down menu) to update with a API response from ngfileupload (sheet names in the file uploaded). I can see the sheet names in what is returned in the browser but cannot get it "into" the select dropdown dynamically.
this.uploader.onSuccessItem=(item,response,status,headers)=>
{
if (response)
{
const res:UploadDataStep1=JSON.parse(response);
const returnDataStep1=
{
Url:res.Url,
SheetNames:res.SheetNames
};
console.log(returnDataStep1.Url);
// this.sheetNames=returnDataStep1.SheetNames;
this.makeTenderStep1_Form.controls['sheetNames'].patchValue(returnDataStep1.SheetNames);
//Input here what needs to happen with data
}
}
and HTML:
<select class="browser-default custom-select"
[ngClass]="{'is-invalid':makeTenderStep1_Form.get('sheetNames').errors&&
makeTenderStep1_Form.get('sheetNames').touched}"
formControlName="sheetNames" id="sheetNames">
<option *ngFor="let name of sheetNames; let i = index" [value]="sheetNames[i]">
{{name}}
</option>
</select>
<ng-template #loading>Awaiting data from uploaded file...</ng-template>
<!-- <span class="form-text text-muted">Please choose which sheet contains the relevant data (Mandatory)</span> -->
<div class="invalid-feedback">You need to select a sheet before continuing</div>
<div class="kt-heading kt-heading--md mt-3">c. Categorise data from file</div>
Found out it was a put request, so could not explicitly work with the return/response from the API (you actually can using Params, but thats a discussion for another day). Changed it to a get request instead which enabled me to work with the return data in the way i wanted.
Related
I am using vuejs3 and I want to make a filter. When user click to the link I want to append the url and push it to browser address bar for now. Later I will do ajax request to update page with product list.
So far I am able to send parameters to URL, but only one item from one group.From first color group I want user to select only one but from second size group I want user to select multiple.
I want this type of URL: localhost:8080/product?color=red&size=medium&size=large
<template>
<div class="products">
<div class="multi_filters">
<h1>Multi Filter By Color</h1>
Red color
Blue color
</div>
<div class="single_filter">
<h1>Multi Size</h1>
Medium
Large
</div>
</div>
</template>
<script>
export default {
data() {
return {
filters:{},
selectedFilters:{}
}
},
methods:{
activateFilter(key,value){
this.selectedFilters = Object.assign({},this.selectedFilters,{[key]:value})
console.log(this.selectedFilters)
this.$router.replace({
query: {
...this.selectedFilters
}
})
}
}
}
</script>
You are expecting size to be an array, this post will helps.
Submitting multi-value form fields, i.e. submitting arrays through GET/POST vars, can be done several different ways, as a standard is not necessarily spelled out.
Three possible ways to send multi-value fields or arrays would be:
?cars[]=Saab&cars[]=Audi (Best way- PHP reads this into an array)
?cars=Saab&cars=Audi (Bad way- PHP will only register last value)
?cars=Saab,Audi (Haven't tried this)
<form
class="" id="form" hx-post="/add/" hx-swap="afterbegin" hx-target="#big_list" hx-trigger="submit">
<input type="text" name="langue1" >
<input type="text" name="langue2">
<div id="errors"></div>
<button type="submit">GO</button>
</form>
<div id="big_list">
.....
</div>
I have a big list in #big_list, and I want my #form appends only one row when submitted.
How with htmx, can I handle errors and show message in #errors ?
I created this solution so you can use hx-target-error = to define which HTML will be displayed after a failed request
document.body.addEventListener('htmx:afterRequest', function (evt) {
const targetError = evt.target.attributes.getNamedItem('hx-target-error')
if (evt.detail.failed && targetError) {
document.getElementById(targetError.value).style.display = "inline";
}
});
document.body.addEventListener('htmx:beforeRequest', function (evt) {
const targetError = evt.target.attributes.getNamedItem('hx-target-error')
if (targetError) {
document.getElementById(targetError.value).style.display = "none";
}
});
If your code raises the errors (validation?), you can change target and swap behavior with response headers.
Response.Headers.Add("HX-Retarget", "#errors");
Response.Headers.Add("HX-Reswap", "innerHTML");
If you want to return a status other than 200, you have to tell htmx to accept it.
4xx would normally not do a swap in htmx. In case of validation errors you could use 422.
document.body.addEventListener('htmx:beforeOnLoad', function (evt) {
if (evt.detail.xhr.status === 422) {
evt.detail.shouldSwap = true;
evt.detail.isError = false;
}
});
It works in htmx 1.8.
If you want to remove the error message on then next sucessfull request, you could use hx-swap-oob. Out of band elements must be in the top level of the response.
So the response could look like this:
<div>
your new row data...
</div>
<div id="errors" hx-swap-oob="true"></div>
Update
You can now use the new powerful extension multi-swap to swap multiple elements arbitrarily placed and nested in the DOM tree.
See https://htmx.org/extensions/multi-swap/
Although it doesn't follow REST principles, you might consider using an swap-oob to report your error back to your user. For example, your request might return a (slightly misleading) status 200, but include content like this:
<div id="errors" hx-swap-oob="true">
There was an error processing your request...
</div>
If it's important to follow REST more precisely, then you'll want to listen to the htmx:responseError event, as mentioned by #guettli in his previous answer.
I am pretty new to vue, and am trying to use it in a bootstrap modal. The relevant div in the modal is as follows.
<div class="form-group row">
<label for="priceQCField" class="col-sm-2 col-form-label">Price<span class="red"> *</span></label>
<input type="number" step="0.01" class="form-control col-sm-4" id="priceQCField" name="priceQCField" min="0" v-model="job.price">
</div>
I read some other questions about vue returning strings rather than numbers, so I have converted the job.price to a number inside my method to call the modal
showPriceJob: function (job) {
this.job = job;
this.job.price = parseFloat(this.job.price);
$('#mdlPriceJob').modal('show');
},
However, job.price refuses to appear in the input field either as a string or a number. I know it is available to the modal as I can see it using <span>{{job.price}}</span>.
Can anyone advise me please?
Additional - I think it is a display issue - if I change the input field, the entry in the <span> changes
2nd update - initial table
<tr class="light-grey" v-for="job in jobs" v-on:click="viewJob(job)">
<td>{{job.id}}</td>
<td>{{job.customerName}}</td>
<td>{{job.description}}</td>
<td v-bind:class="job.dueDate | dateColour">{{job.dueDate | dateOnly}}</td>
<td>£{{job.price}} {{job.isEstimate | priceEstimated}}</td>
<td>{{job.delivery}}</td>
</tr>
Upd.
According to your comments to my answer you are using v-for and you can't use this.job within your method. You should give us more code to see the whole picture.
Upd.2
You have showed more code but I didn't see any v-for so I am confused. You can try to use something like this if job is a property of appData.jobs:
showPriceJob: function (job) {
this.appData.jobs.job = Object.assign({}, job);
this.appData.jobs.job = parseFloat(this.appData.jobs.job.price);
$('#mdlPriceJob').modal('show');
},
But I'm not sure about this because I don't see where job is declared.
Upd.3
Oh! Wait! You have this code:
data: appData.jobs, but data should be in this format:
data: function(){
return {
appData: {
jobs: [],
},
}
},
Or show me what is your appData.jobs variable is.
I have this collection called servers which is like this: {id, name, code}.
I have this select tag, I iterate over my servers collection and the data() with the model values.
<select v-model="serveur">
<option v-for="server in servers" :key="server.id" :value="server.name">
{{server.name}}
</option>
</select>
.
.
.
data () {
return {
serveur:'',
code:''
}
}
The value "server.name" selected is binded to the model "serveur".
All of this works just fine, but I want the value "server.code to be binded to the model "code"
I can't figure out how to do this. I'm new to vuejs, like I've been working with vue for the first time only two days ago.
This is also my first Stack Overflow "asks" so I hope I am being clear enough.
Thanks in advance.
You really have one independent data item, which I will call selectedServer. It gets the value of the server entry, which contains both name and code.
<select v-model="selectedServer">
<option v-for="server in servers" :key="server.id" :value="server">
{{server.name}}
</option>
</select>
You can simply refer to selectedServer.name and selectedServer.code in the URL you need to assemble from them, or you can create computeds to return those values under whatever names you prefer, like
data: {
selectedServer: {}
},
computed: {
serveur() { return this.selectedServer.name; },
code() { return this.selectedServer.code; }
}
To achieve this, you can bind the select with an array containing 'serveur' and 'code'. But you can't bind the select with multiple variables directly.
You can do comething like that:
<select #input="serveur = $event.name; code = $event.code">
<option v-for="server in servers" :key="server.id" :value="server">
{{ server.name }}
</option>
</select>
If you need fiddle - feel free to ask. It is possible that this example not working :)
I believe you can find an answer here:
https://stackoverflow.com/a/50982485/10954996
that is something I would do - create change handler and change everything I need within handler method
I hope this helps
I have simple requirement Let's take an example
EX1:
In My View I have two Input fields
First Name and Last Name and one button submit to save first name and Last name.
Now I want that my submit button gets enabled only when there is any change in first name and last name value.
EX2:
In My View I have two Input fields
First Name and Last Name and one button submit to save first name and Last name.
Now here first name and last name having value from my view-model. if i change anything for first name and last name my submit button gets enabled, now again if i put previous value for first name and last name my submit button gets disabled.
<template>
<form role="form" submit.delegate="SaveDetail()" validate.bind="validation">
<div class="form-group">
<label>First Name</label>
<input type="text" value.bind="firstName" class="form-control">
</div>
<button class="btn btn-success" type="submit" disabled.bind="!validation.result.isValid">save</button>
</form>
</template>
import {inject} from 'aurelia-framework';
import {Validation} from 'aurelia-validation';
#inject(Validation)
export class ChildRouter {
firstName: string = 'pranay';
validation;
constructor(Validation) {
var self = this;
self.validation = Validation.on(self)
.ensure('firstName')
.isNotEmpty()
.hasMinLength(3)
.hasMaxLength(10)
.isNotEqualTo(self.firstName);
}
SaveDetail() {
var self = this;
self.validation.validate()
.then(() => {
alert(self.firstName);
});
}
}
Please let me know the best approach for this type of scenario.
Try to track 'dirty' values with validation rule isNotEqualTo(oldValue) and just check if result is valid.
<button disabled.bind="validation.result.isValid"></button>
UPDATE: But when model is refreshed, like after saving, validation object should be re-initialized too. Also for earlier versions it was advised to call this.formValidation.destroy();, not sure if it is needed now.