I'm using angular-archwizard andI want to validate a field with a request before go to the next step.
The function is performed but doesn't render the change until I manipulate the form again.
in controller:
#ViewChild('wizardform') wizard: WizardComponent;
checkCompanyName() {
this._CompaniesService.checkCompanyName(this.company.name).subscribe( (data: any) => {
this.wizard.goToNextStep();
this.ref.detectChanges();
}, err => {...});}
I expected the form render to the next step.
Related
Context description
I have a Vue 3 project and using element plus, I created a form with async validation. The code of validation function (Laravel precognition):
const validatePrecognitive = async (rule: InternalRuleItem, value: Value, callback: (error?: string | Error) => void) => {
return new Promise<void>((resolve, reject) => {
if (!rule.field) {
return;
}
precognitive.post('/events', computedFormData.value, {
validate: [rule.field],
onPrecognitionSuccess(response) {
if (response.status === 204) {
callback();
resolve();
}
},
onValidationError(response) {
callback(new Error(response.data.message));
reject();
},
});
});
};
and I define the rules like this:
const rules: FormRules = reactive({
} as Partial<Record<string, Arrayable<FormItemRule>>>);
// dynamically set the rules for each input, because of same value for all rules
Object.keys(getSubmitShape()).forEach(key => {
rules[key] = [{ asyncValidator: validatePrecognitiveDebounced, trigger: 'blur' }];
});
The getSubmitShape() funtion return Object with all form-item keys, that should be validated. So you can imagine it like:
const rules: FormRules = reactive({
rules['name'] = [{ asyncValidator: validatePrecognitive, trigger: 'blur' }];
rules['surname'] = [{ asyncValidator: validatePrecognitive, trigger: 'blur' }];
}
This works like a charm, when I write to inputs and switch between them. The errors would appear and dissappear correctly.
Submit
When the form is submitted, I am calling formEl.validate(...) function, which should validate all the inputs. It works, BUT:
for every rule item, one HTTP request is sent to server, because the validation method is called for each rule separately.
What I tried
I tried to implement debounce method, which would save the params from each previous function call and include that in next call, so in a last call, I would have all the inputs, rules and callbacks available. This works, when I try it while writing inputs to elements and switching them fast (triggering validation).
When on submit, it waits the debounce time for each rule. So the requests again go one by one with the delay of debounce time.
Any ideas, how I could make this in one request?
Thanks.
I have code in Nodejs as backend and Angular as frontend.
I want to receive and send data by one endpoint and based on that data from server toggle a button. Toggling is working now but I want when I sign out from the dashboard next time that I log in I could see the value of the key is based on the value from the database.
For example, first, it's SET after clicking it changed to CLEAR and I sign out from the dashboard. When next time I log in I want to see the CLEAR label on my button.
These are codes for several parts of the app:
Angular Service
this.setUserFeatured = function(id, setFeatured) {
return $http.put('/admin/v2/users/' + id + '/featured', { setFeatured: setFeatured })
.then(returnedDataOrError);
};
Angular Controller
function updateFeaturedButtonLabel() {
$scope.featuredButtonLabel = $scope.user.setFeatured ? "Clear Featured" : "Set Featured";
}
function toggleFeatured () {
$scope.user.setFeatured = !$scope.user.setFeatured;
UserService.setUserFeatured($stateParams.id, $scope.user.setFeatured)
updateFeaturedButtonLabel();
};
Html File
<a class="btn btn-info" ng-click="toggleFeatured()" ng-class="{on:user.setFeatured}">{{featuredButtonLabel}}</a>
Server Controller
function addFeaturedUser(req: $Request, res: $Response, next: NextFunction) {
const schema = Joi.object().keys(_.pick(validate, ['userId', 'setFeatured']));
const queryParams = { userId: req.params.id };
if (!req.params.id) {
return new errors.BadRequest('userId is not specified');
}
return validate.validate(queryParams, schema)
.then(validatedParams =>
userService5.updateUserLabel(validatedParams.userId, req.body.setFeatured))
.then(result => res.json(result))
.catch(next);
}
router.put('/users/:id/featured', addFeaturedUser);
And updateUserLabel is a function that handling the connection to the database and retrieving the data.
I just wonder how can I use the data from the server to change the label of the button?
true/false for the setting the button is coming from the .then(result => res.json(result))
Thanks in advance for help
For your question, I suppose you are asking how to use the response object returned in
$http.put().then(function(response){})
You can find the structure of response object in following document.
https://docs.angularjs.org/api/ng/service/$http
To access the data returned from server:
$http.put().then(function(response){response.data})
which corresponds to what your server sends.
Besides, the toggleFeatured function should be add to $scope object.
Otherwise, ng-click can't trigger that function in html template.
Hope it helps.
So I want to make a PUT request to the server, but it doesn't want to work. I know that when making a PUT request you need an identifier(e.g id) for the resource and the payload to update with. So that is my problem.
In my form I have these props:
<div>
<DoorSettingsForm
onSubmit={this.submit.bind(this)}
item={this.props.location.state.item}
id={this.props.location.state.item._id}
/>
</div>
item - All the input fields, radiobuttons etc.
id - The identifier
onSubmit - the function that handles the submitting of all of the new data, here it is:
submit(values, id) {
this.props.updateSettings(values, id)
}
And inside of my really simple action I have this:
export function updateSettings(id, item) {
return dispatch => {
console.log('ID: ', id)
return axios
.put(`${settings.hostname}/locks/${id}`, item)
.then(res => console.log(res))
.catch(err => console.log(err))
}
}
One thing that I really don't understand is when I change the places of id and item on the first line the output of my console.log changes. When having id as the first parameter I get everything I've typed in my inputs (the changes) and when having item as the first parameter I'm getting this:
ID: function (action) {
if (action.payload) {
if (!(0, _isPromise2.default)(action.payload) && !(0, _isPromise2.default)(action.payload.promise)) {
return next(action);
}
Any help with my problem is really appriciated! Thanks for reading.
I forgot to call handleSubmit with my id:
form onSubmit={() => handleSubmit(id, item)}
There is an electron framework that gives you a stripped down browser to build your user interface for the desktop application. In my case, I am using jQuery for DOM navigation, Sequelize to talk to my sqlite database and a couple other libraries.
Let's say I have a text field where the user can type a movie name. My database stores a couple hundred movie names. So I would like to offer the user autocomplete suggestions.
Typically, I would use something like this to register a jQuery handler (this will echo field input back to console):
$('#movie-search-field').on('input', (event) => {
console.log(event.target.val())
})
With sequelize, you would typically have a model (say, Movie) and query it like so: Movie.findAll(). Here comes the problem:
If I register my handler like so:
Movie.findAll().then((movies) => {
$('#movie-search-field').on('input', (event) => {
/*Use movies here to build and show a suggestions list*/
})
})
then it never gets triggered. I have verified that the .then clause is entered by printing movies to console from within it.
On the other hand, if I try to query the database from inside the handler:
$('#movie-search-field').on('input', (event) => {
Movies.findAll().then((movies) => {
/*Use movies to build and show a suggestions list*/
})
})
then the handler exits before the promise is resolved and no suggestions are shown.
How could I use the database query results in my event handler?
You could just make a simple callback
$('#movie-search-field').on('input', (event) => {
getResults(function(movies) {
/* Display your movies */
})
})
function getResults(callback) {
Movies.findAll().then((movies) => {
/*Use movies to build and show a suggestions list*/
callback(movies)
})
}
So when a user types in the input box it will request the suggestions and then when it returns them it will call the function (callback) and then you can display them
Turns out I made some unrelated mistakes in my event handler code and so the approach I described above works just fine:
Movie.findAll().then((movies) => {
$('#movie-search-field').on('input', (event) => {
/*Use movies here to build and show a suggestions list*/
})
})
Also, if you are doing several database queries and would like your handler to have access to all of those, you can do:
let movies = Movie.findAll()
let tickets = Ticket.findAll()
Promise.all([movies, tickets]).then(values => {
let [movies, tickets] = values
/* register your handlers here and pass the data to them */
$("#some-selector").on('input', {movies: movies, tickets: tickets}, (event) => {
let movies = event.data.movies
let tickets = event.data.tickets
/* some event handling code that uses both movies and tickets */
})
})
I am using ember. I intercept one component's button click in controller. The click is to trigger a new report request. When a new report request is made, I want the newly made request to appear on the list of requests that I currently show. How do I make ember refresh the page without obvious flicker?
Here is my sendAction code:
actions: {
sendData: function () {
this.set('showLoading', true);
let data = {
startTime: date.normalizeTimestamp(this.get('startTimestamp')),
endTime: date.normalizeTimestamp(this.get('endTimestamp')),
type: constants.ENTERPRISE.REPORTING_PAYMENT_TYPE
};
api.ajaxPost(`${api.buildV3EnterpriseUrl('reports')}`, data).then(response => {
this.set('showLoading', false);
return response.report;
}).catch(error => {
this.set('showLoading', false);
if (error.status === constants.HTTP_STATUS.GATEWAY_TIMEOUT) {
this.notify.error(this.translate('reports.report_timedout'),
this.translate('reports.report_timedout_desc'));
} else {
this.send('error', error);
}
});
}
There are few think you should consider. Generaly you want to have variable that holds an array which you are render in template in loop. For example: you fetch your initial set of data in route and pass it on as model variable.
// route.js
model() { return []; }
// controller
actions: {
sendData() {
foo().then(payload => {
// important is to use pushObjects method.
// Plain push will work but wont update the template.
this.get('model').pushObjects(payload);
});
}
}
This will automatically update template and add additional items on the list.
Boilerplate for showLoading
You can easily refactor your code and use ember-concurency. Check their docs, afair there is example fitting your usecase.