I have a Laravel 5.2 Backend API and a AngularJS Frontend and at some point I perform a laravel validation and return and error if validation fails.
When I iterate trough errors and display them on the frontend I get somthing like this:
["The email has already been taken."]
and I would like to be like this
The email has already been taken.
without the [""] stuff.
My code is:
Angular controller:
if (error.statusText === "Unprocessable Entity") {
$scope.registerErrors = error.data;
}
Angular template:
<div class="alert alert-warning animated pulse" ng-if="registerError && isLoading === false">
<p ng-repeat="(error, errorText) in registerErrors">{{errorText}}</p>
</div>
Laravel controller:
$this->validate($request, [
'firstname' => 'required|max:100|min:3',
'lastname' => 'required|max:100|min:3',
'email' => 'required|email|unique:users|max:255',
]);
Console.log:
Thanks in advance!
because of errorText contain email array and you shown full email array. if email contain multiple error then
can try like:
<p ng-repeat="(error, errorObject) in registerErrors">
<span ng-repeat=" singleError in errorObject">{{singleError}}</span>
</p>
or for single error can try like:
<p ng-repeat="(error, errorText) in registerErrors">{{errorText[0]}}</p>
or just assign error.data.email instead of error.data
if (error.statusText === "Unprocessable Entity") {
$scope.registerErrors = error.data.email;
}
Actually you need change $scope.registerErrors = error.data; into $scope.registerErrors = error.data.email;. Because error.data.email is an array.
If you have several errors at the same time, it's better to try this
if (error.statusText === "Unprocessable Entity") {
$scope.registerErrors=[];
if(error.data.email)$scope.registerErrors.push(error.data.email[0]);
if(error.data.firstname)$scope.registerErrors.push(error.data.firstname[0]);
if(error.data.lastname)$scope.registerErrors.push(error.data.lastname[0]);
}
Working fiddle: https://jsfiddle.net/udr9dksa/
{{emailTaken | cleanError}}
Filter:
app.filter("cleanError", function() {
return function(input) {
if(!input) return "";
return input.slice(2, -2);
}
});
Related
I have the following JavaScript method for loading the messages in a mini chat app. The idea is that I have two HTML classes to position the message either on left or right depending on who sent it. The HTML and CSS are fine and work properly. My question is when it comes down to getting the messages from Firestore.
I have the following messages in order from first sent to last: Hello, hyd?, Good, Hello Sir, hey
But somehow strangely they are not ordered properly when displayed on the screen, I get first the messages sent from other user then it displays my messages. I am not sure where I messed up the code for this behavior but I somehow believe it has to do with the if statement where I check who sent the message. The document of a message in Firestore has the following structure:
{
createdAt: ....,
message: ....,
from: ....,
to: ....
}
let divMessagesLeft = document.getElementById("firstmessages--main-div-id");
let devMessagesRight = document.getElementById("firstmessages--main-div-id-2");
async function loadMessages() {
firebase.auth().onAuthStateChanged(async function (user) {
if (user) {
let messagesReference = firebase
.firestore()
.doc(`/chats/${user.displayName}`)
.collection(`/chats/${userChat.username}/messages`)
.orderBy("createdAt");
await messagesReference
.get()
.then(function (snapshot) {
snapshot.forEach(function (doc) {
console.log(doc.data().message);
if (doc.data().from === userChat.username || doc.data().to === user.displayName) {
const message = `<div class="messagee">${doc.data().message}</div>`;
divMessagesLeft.innerHTML += message;
} else {
const message = `<div class="messagee messagee-right">${doc.data().message}</div>`;
devMessagesRight.innerHTML += message;
}
});
});
} else {
console.log("Not logged in");
}
});
}
loadMessages();
<div id="chat-messages-main-div-id" class="chat-messages-main-div">
<div id="first-message-div-id" class="first-message-div">
<div id="firstmessages--main-div-id" class="firstmessages--main-div">
<!-- <div class="messagee">Hello</div> -->
</div>
</div>
<div id="first-message-right-id-2" class="first-message-right">
<div id="firstmessages--main-div-id-2" class="firstmessages--main-div">
<!-- <div class="messagee messagee-right">Hi</div> -->
</div>
</div>
</div>
I would try to replace the "||" operator with "&&", which is a more correct check to do.
(it will fail if you'll try messaging yourself, and you should think how you want to implement this scenario).
Also I think you need to add "desc" to the "order by" method.
as the title says I build a CRUD application using Angular 5 and CRUD works just fine but now I need to retrieve a specific post data with advanced routing so the url should be something like :
https://example.com/blog/howtoDoSomething
and the page should contain this post details like name, content , image and so on .
I tried
details.component.ts
this.sub = this.route.params.subscribe(params => {
this.key = params['$key'];
});
details.component.html
<p>
this page about {{ $key }}
</p>
the above code worked fine with angular 4 with some difference of course and I used a json file not Firebase .
I also tried this one :
details.component.ts
var x = this.blogService.getData();
x.snapshotChanges().subscribe(item => {
this.blogList = [];
item.forEach(element => {
var y = element.payload.toJSON();
y["$key"] = element.key;
this.blogList.push(y as Blog);
});
});
details.component.html
<div *ngFor="let blog of blogList">
{{blog[$key].title}}
</div>
this one if I use blog alone like :
<div *ngFor="let blog of blogList">
{{blog}}
</div>
this retrieves the whole database as as
[object object] repeated
thanks in advance .
// user-service.ts
public getUser(userId: string) {
return this.afs.doc('users/' + userId).valueChanges();
)
// user-component.ts
// Get userId from route
this.user$ = this.userService.getUser(userId);
// user-component.html
<div *ngIf="user$ | async as user">
{{user | json}}
</div>
I am trying to show Success message , once the data is updated in my application. Success function is working properly , but message is not getting generated. when I click on the save() button, small alert box will display, but message wont appear.
HTML : <div class="alert alert-success" ng-show="successmessage">{{cts.success_info}}</div>
Angular Js:
$scope.successmessage = function(){
$scope.cts = [];
$scope.cts.success_info = "Data Successfully got updated";
}
You defined successmessage as a function, but using it as a value.
If you need to display alert on success call of save function, use success function below. It creates an object with a message and isSuccess flag:
Html:
<div class="alert alert-success" ng-show="cts.isSuccess">{{ cts.message }}</div>
JS:
$scope.success = function() {
$scope.cts = {
isSuccess: true,
message: 'Data Successfully got updated'
};
}
Working demo
You can take advantage of *ngIf if want to display more then just simple string like below:
showMsg: boolean = false;
onSubmit() {
this.userService.createUser(this.addForm.value)
.subscribe( data => {
this.router.navigate(['list-user']);
this.showMsg= true;
});
}
then you can use showMsg boolean to show/hide dive like below
<div class="col-md-6">
<div ng-click=="onSubmit()">
<div class="row" *ngIf="showMsg">
<div class="col-xs-12">
<p class="alert alert-success">
<strong>Registration Success!</strong> Please click here to login!.
</p>
</div>
</div>
<button class="btn btn-success">Add user</button>
</div>
</div>
note that I am using some bootstrap classes for styling.
Yes function must return something . If you want a better option , you can use toast or popover .
Do this,
<div class="alert alert-success" ng-show='cts.showmsg == true'>{{cts.success_info}}</div>
You can use one boolean variable to show/hide message.
Angular Js:
$scope.successmessage = function(){
$scope.cts = [];
$scope.cts.success_info = "Data Successfully got updated";
$scope.cts.showmsg = true;
}
If you want to display in popup or modal, then there is best library in angular called ngDialog
I have created a function that does some error checkings and will be used in different input fields. My function code is below:
errorChecks = (element, minlength) => {
if (element.$dirty) {
if (element.$error.required == true) {
this.errorMessage = "REQUIRED";
return;
} else if (element.$viewValue.length < minlength) {
this.errorMessage = "MINLENGTH" // MINLENGTH error with parameters here
return;
} else {
this.errorMessage = null;
return;
}
}
}
I am using the angularjs translate for my error messages.
"MINLENGTH": "{{ element }} must be at least {{ value }} characters",
I wanted to dynamically change my error message by passing a parameter to the translations like so:
errorChecks(username, 5);
If I enter 1 character to the username field the error would say: username must be at least 5 characters.
Is what I am trying to do even possible?
It'll probably be best if you translate inside the controller for this one, unless you want to pass element and minlength to the template.
Firstly you'll need inject $translate into your controller. Then to generate your message:
this.errorMessage = $translate('MINLENGTH', { element: element, value: minlength });
This method is also outlined here.
To do this in the template (outlined here):
{{ MINLENGTH | translate : { element: element, value: minlength } }}
For anyone wondering how the syntax is, for using methods to retrieve the input for translation, this worked for me:
{{ MINLENGTH | translate : { x: table.getShownCount(), y: table.getTotalCount() } }}
You can also do this in the template like this.
<span data-translate="MINLENGTH" data-translate-values="{ element: element, value: minlength }"></span>
You can also use $translate.instant('MINLENGTH', { element: element, value: minlength })
This worked fine for me:
{{'commisionMessage' | translate : {fee:fee} }}|
Json File
"commisionMessage": "BLA {{fee}} BLA BLA"
I'm trying to replace some html code with Javascript when a user searches for an email. I have it working correctly, but for some reason the error displays around 20+ times, so it will replace the div and say
"user does existuser does existuser does existuser does existuser does existuser does exist"
instead of just putting the error message once. Any idea how I can fix it?
$scope.checkEmail = function
findUsersMatchingEmail(emailAddress) {
ref.child('users').orderByChild('email').
equalTo($scope.emailAddress).once('value', function (snap) {
var output = '<div>',
myError = document.querySelectorAll('#d');
for (var key in arguments[0]) {
output += (snap.name() +
(snap.val() === null ? ' Does Not' : ' does') + ' exist');
}
output += '</div>';
for (var i = myError.length - 1; i >= 0; i--) {
myError[i].innerHTML = output;
}
});
};
As I wrote in the comments, never manipulate the DOM from anywhere but the link function of a directive. Explaining why is probably out of scope for this answer, and has been answered multiple times here on SO. A very good read is:
“Thinking in AngularJS” if I have a jQuery background?
and A Conceptual Introduction to AngularJS
So to make it short, here's a very simple demo of how you could handle your error messages.
Note that this is by no means the only nor the best way to do it. There's ngMessages or form validation in general which could be used as well.
(function (app) {
'use strict';
app.controller('EmailCtrl', ['$scope', function ($scope) {
$scope.errors = [];
$scope.checkEmail = function findUsersMatchingEmail(emailAddress) {
// clear previous errors
$scope.errors.length = 0;
// check email and add errors if needed
// using your service (ref)
$scope.errors.push({
message: 'email not unique ' + (Math.random()) // random is only used to show that the errors actually change
});
};
}]);
})(angular.module('app', []));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
<div data-ng-app="app" data-ng-controller="EmailCtrl">
<ul>
<li data-ng-repeat="error in errors">{{ error.message }}</li>
</ul>
<form data-ng-submit="checkEmail(email)">
<input data-ng-model="email" placeholder="email">
</form>
</div>
Side note: I would normally use the controller as syntax, though I did not want to introduce any more new topics.