I have a bootstrap form where user enter an email I want if user doesn't enter #scoops.com it concatenates automatically either form side or controller side
In controller it saves using this $customer->email = $request->email; if want to check at controller side how I can check if user enters #scoops.com at the end of user name. If it is missing then concatenate #scoops.com with user name
<div class="form-group">
<label>Email <span style="opacity: 0.5; font-style: italic; color: red;">(Required)</span></label>
<div class="input-group">
<input type="search" name="email" id="email" autocomplete="off" class="form-control input-lg" placeholder="Enter Email" name="name" required="#scoops.com" / onfocus='tmp=this.value;this.value=""' onblur='if(this.value=="")this.value=tmp'>
<div class="input-group-append">
<span class="input-group-text">#scoops.com</span>
</div>
</div>
<ul id="suggested-emails" class="list-group"></ul>
<span id="error_email"></span>
#if($errors->has('email'))
<div class="alert alert-danger">
{{ $errors->first('email') }}
</div>
#endif
</div>
`
Something like:
$customer->email = $request->email;
if (!preg_match('/^.*#scoops.com$/', $customer->email)) {
$customer->email .= '#scoops.com';
}
The risk is if they put in anything#example.com, you'll then get anything#example.com#scoops.com. It probably needs something additional to check if it looks like an email address already (i.e. has at least an "#" in it).
First of all you will check if #scoop.com is present or not like below:
use Illuminate\Support\Str;
$myString = '#scoop.com';
$contains = Str::contains($request->email, '#scoop.com');
$contains will either true or false
if it's false then concatenate #scoop.com as below
$newString = $request->email.$myString;
Related
In my database i have many users which has many recipes.
Every recipe has some properties and collection of ingredients.
Below is screenshot
Recipe with all properties
So when user display recipe to edit on page should appear (form) recipe with loaded current data. This is kind of working because i can see the data but i think it's no done good.
I have form which is working fine without array (ingredients). Could you tell me how i should add ingredients to my edit form?
I'd be grateful if you see at my code and give me feedback and hints what i should change.
export class RecipeEditComponent implements OnInit {
#ViewChild('editForm') editForm: NgForm;
recipe: IRecipe;
photos: IPhoto[] = [];
ingredients: IIngredient[] = [];
uploader: FileUploader;
hasBaseDropZoneOver = false;
baseUrl = environment.apiUrl;
currentMain: IPhoto;
constructor(private route: ActivatedRoute, private recipeService: RecipeService,
private toastr: ToastrService) { }
ngOnInit(): void {
this.loadRecipe();
}
loadRecipe() {
this.recipeService.getRecipe(this.route.snapshot.params.id).subscribe(recipe => {
this.recipe = recipe;
this.initializeUploader();
})
}
updateRecipe(id: number) {
this.recipeService.editRecipe(id, this.recipe).subscribe(next => {
this.toastr.success('Recipe updated successfully');
this.editForm.reset(this.recipe);
}, error => {
this.toastr.error(error);
});
}
}
HTML
<div class="container mt-4 border" *ngIf="recipe">
<form #editForm="ngForm" id="editForm" (ngSubmit)="updateRecipe(recipe.id)" >
<h5 class=" text-center mt-2">Recipe details:</h5>
<div class="form-group mt-3">
<label for="city">Name</label>
<input class="form-control" type="text" name="name" [(ngModel)]="recipe.name">
</div>
<div class="form-group">
<app-ingredient-editor [ingredients] = "recipe.ingredients"></app-ingredient-editor>
<div *ngFor="let ingredient of recipe.ingredients; let i = index">
<input class="form-control" type="text" name="{{ingredient.name}}" [(ngModel)]="ingredient.name">
<input class="form-control" type="text" name="{{ingredient.amount}}" [(ngModel)]="ingredient.amount">
</div>
</div>
<div class="form-group">
<br>
<p>Add recipes</p>
</div>
<h5 class=" text-center mt-4">Description</h5>
<angular-editor cols=100% rows="6" [placeholder]="'Your description'" [(ngModel)]="recipe.description" name="description"></angular-editor>
</form>
<button [disabled]="!editForm.dirty" form="editForm" class="btn btn-success btn-block mb-5 mt-5">Save changes</button>
</div>
For now it's look like:
Form on page
When i delete ingredient name while changing on the console i have following error:
recipe-edit.component.html:12 ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form
control must be defined as 'standalone' in ngModelOptions.
Problem is that part of code:
<div *ngFor="let ingredient of recipe.ingredients; let i = index">
<input class="form-control" type="text" name="{{ingredient.name}}" [(ngModel)]="ingredient.name">
<input class="form-control" type="text" name="{{ingredient.amount}}" [(ngModel)]="ingredient.amount">
</div>
</div>
But i don't know how to make it working..
How to add add array to template-driven form?
In my case i need to display current ingredients and be able to edit them.
I have tried something like this :
<input class="form-control" type="text" name="ingredient[i].name" [(ngModel)]="ingredient[i].name">
<input class="form-control" type="text" name="ingredient[i].amount" [(ngModel)]="ingredient[i].amount">
But id doesn't work
The problem is that the property name on the form must be defined in order for angular to know which input to update. You're binding name to the same property that the editable model is set to which means the user can edit it and in fact delete it, which isn't good.
The solution is to change it to a unique value that doesn't change. This should work:
<div *ngFor="let ingredient of recipe.ingredients; let i = index">
<input class="form-control" type="text" name="name{{ingredient.id}}" [(ngModel)]="ingredient.name">
<input class="form-control" type="text" name="amount{{ingredient.id}}" [(ngModel)]="ingredient.amount">
</div>
</div>
Link to stackblitz showing it working: https://stackblitz.com/edit/angular-10-base-template-q243lw?file=src%2Fapp%2Fapp.component.html
Edit: fixed bug in original post and added link to stackblitz
I am working on my form validation and I want to display different error message according to the error I get. I am using Silex and Twig with the translator component and balloon.css for the tooltip and it works so far.
Now I want to translate this error message according to the langage of my website and I have some trouble to do what I want.
Here is my code :
My form
<form class="my-form col-12 col-md-5">
<div class="form-group">
<label for="name" class="col-12">
<input type="text" class="form-control color-light-grey" id="name" name="name" aria-describedby="name" placeholder="{{ 'input-name'|trans }}">
</label>
<small>www.mywebsite.com/<span id="input_name_content">______________</span></small>
</div>
<div class="form-group">
<label for="name" class="col-12">
<input type="password" class="form-control color-light-grey" id="mdp" name="mdp" placeholder="{{ 'input-password'|trans }}">
</label>
</div>
<div class="form-group">
<label for="name" class="col-12">
<input type="password" class="form-control color-light-grey" id="confirm_mdp" name="confirm_mdp" placeholder="{{ 'input-confirm'|trans }}">
</label>
</div>
<button id="create_new" type="button" class="btn bg-color-yellow hover-yellow-light">{{ 'create-pixers'|trans }}</button>
</form>
As you can see, I use {{ 'key'|trans }} to translate my content and it's ok.
My JS
I have a function that check my input value and create an error when I meet one, then at the end if my error obj is not empty I display my error. I use this function to do it, it adds some balloon.css attribute so I have what I want :
function displayFormError(error) {
$.each(error, function(key, msg) {
$("input[name='"+key+"']").parent().parent().attr({
"data-balloon-visible": "",
"data-balloon-pos" : "up",
"data-balloon" : msg
});
$("input[name='"+key+"']").parent().addClass("is-wrong").removeClass("is-valid");
});
}
My problem
When I do this in my HTML, it works (I have my tooltip with the empty error message) :
<div class="form-group" data-balloon-visible data-balloon-pos="up" data-balloon="{{ 'empty'|trans }}">
<label for="name" class="col-12">
<input type="text" class="form-control color-light-grey" id="name" name="name" aria-describedby="name" placeholder="{{ 'input-name'|trans }}">
</label>
</div>
But when I use displayFormError(error) with msg = "{{ 'empty'|trans }}" it doesn't works.
I know it's because I do it in JS, but is it possible to add my message as I want from my JS to my Twig template?
I saw this bundle that could help me maybe, but i'd like to find a solution I can do myself if possible: https://github.com/willdurand/BazingaJsTranslationBundle
No, it's impossible to pass your variable from Javascript to Twig(PHP).
I would use https://github.com/willdurand/BazingaJsTranslationBundle to avoid using 2 different system of translation in your application.
This way you will have your javascript and your message in a same file.
If you really want to do it yourself, you can re-invent the wheel : it's just some text being replaced by another. Or you can find a javascript library.
Well, in fact I manage to solve my problem by adding my Javascript in a Twig Block.
So this code in script.js won't work :
function displayFormError(error) {
$.each(error, function(key, msg) {
$("input[name='"+key+"']").parent().parent().attr({
"data-balloon-visible": "",
"data-balloon-pos" : "up",
"data-balloon" : msg // msg = "{{ 'my-key'|trans }}"
});
$("input[name='"+key+"']").parent().addClass("is-wrong").removeClass("is-valid");
});
}
But if you add it in a Twig Block in your "my_view.html.twig" file it will :
{% block ADD_JS_CODE %}
<script type="text/javascript">
$(document).ready(function() {
function displayFormError(error) {
// same code than before
}
});
</script>
{% endblock %}
This way I can use my function that check my form and add message according to the error in the current langage in the page, without any other component, just Silex + Twig + Translator !
i have a form which sends the following data to the server:
<!-- This form pulls, using JS event handlers, data from the table record selected -->
<form id="edit_form" action="" method="POST" role="form">
{{ csrf_field() }}
{{ method_field('PATCH') }}
<div class="form-group">
<label>ID do Cartão</label>
<input type="text" class="form-control" name="idcartao_edit" placeholder="ID do Cartão" value="" />
</div>
<div class="form-group">
<label>Nome do aluno</label>
<input type="text" class="form-control"
name="nome_aluno_edit" placeholder="Nome do Aluno" value="" />
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" name="email_edit" placeholder="E-mail" value="" />
</div>
<div class="form-group">
<label>Curso</label>
<select id="curso_edit" class="form-control" name="curso_edit">
<option>Seleccionar curso...</option>
#foreach($curso_list as $curso)
<option value="{{$curso->encrypted_id}}">{{$curso->curso}}</option>
#endforeach
</select>
</div>
<div class="form-group">
<label>Triénio</label>
<!-- Trigerred by a JS event handler when a curso_edit option is selected -->
<select id="trienio_edit" class="form-control" name="trienio_edit">
<option>Seleccionar triénio...</option>
</select>
</div>
<!-- Triggered when user opens a bootstrap modal. Pulls the value from the table record selected -->
<input type="hidden" id="idcartao_original" name="idcartao_original" value="" />
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Editar aluno</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Fechar</button>
</div>
</form>
on the server side, the data inputed by the user is processed like this:
public function update(Request $request, Aluno $aluno)
{
$id_aluno = $aluno->where('id_cartao', '=', $request->input('idcartao_original'))->first()->id;
$aluno = $aluno->find($id_aluno);
$aluno->id_cartao = $request->input('idcartao_edit');
$aluno->nome = $request->input('nome_aluno_edit');
$aluno->email = $request->input('email_edit');
$aluno->trienio_id = decrypt($request->input('trienio_edit'));
$aluno->save();
return redirect()->route('alunos');
}
the problem with this form is that the user can change the id to a different one, and the query will load an entirely non-intended different user. like changing the value from 1 to 2, for example, on this input field:
<input type="hidden" id="idcartao_original" name="idcartao_original" value="" />
so instead of loading a model like this:
ID: 1
ID Cartão: 1011000
Nome: Joseph Wilson
E-mail: joseph.67#gmail.com
it will load a model like this:
ID: 2
ID Cartão: 1011001
Nome: John Black
E-mail: johnblackwilliams#gmail.com
and proceed to change the data of a, like i said, an entirely non-intentional different model.
i've already tried to send encrypted ids using an ajax call to the server but considering the inputs can end up like this:
curso_edit option (the encrypted values are the encrypted ids of the "TAI" option, for example)
<option value="eyJpdiI6ImJqZGJKOGVBOFMyQ0huUXdKVHhFMXc9PSIsInZhbHVlIjoidWpROWRrSUFYREszbTF2Q24zTkVoZz09IiwibWFjIjoiM2QxYWViNzU0NWIyN2M2ZGQzMmMwYWJjYWUxZTAyYzBkOGNlNWQ0MDAzMjIyNzA1YWExNzg5ODA2MmNhYjBiMCJ9">TAI</option>
<option value="eyJpdiI6IjRVMWowT0cwYWxVeWpOXC9YaW0yRlJnPT0iLCJ2YWx1ZSI6IkF1VmZoTGdPT3BsTnR3MWV0bXhGdkE9PSIsIm1hYyI6ImY2ZDRiOGIyZDFmMjdmNjhkYzA4ZDMzNGVmNzY2NWZkYzhiMzA1ODljMmM1Njk3ODA1ZGFkZjQ4MWI5ZGM4MzcifQ==">TAL</option>
and so on...
trienio_edit option
<option value="eyJpdiI6ImpmTjBHSk8zTzQ0NmFLR0t1SkxhVXc9PSIsInZhbHVlIjoiOTFYOEluYXFWQk4xMVYxYk1JUHZ0Zz09IiwibWFjIjoiMWZhZDU0NmE2MWQwODliYzg3ZDEzM2Q5NTM3NWJiYTUxMzM5ZTQyMjMwMDBjZDI2OGE4ODEyZjAzNjk3MTVlYyJ9">2015-2018</option>
<option value="eyJpdiI6IjhvUTNGbnNZbG1Ja0d0NktFZFRNaGc9PSIsInZhbHVlIjoicGdKeWtZa1VEeHpDTzQ5QVFhRHcrdz09IiwibWFjIjoiM2EwM2IzZDY3Y2VmZWI4N2QzNTUyZGVlMTUxNjVkZjFiOWUzNGViYjdiNTFiMGZmMDEwMjBhY2JlYTg3ZDg3MiJ9">2014-2017</option>
and so on...
even if the user doesn't have access to the ids in their raw state, he can still inspect the element using chrome or other browser and pull the encrypted id corresponding to the curso/trienio they want to maliciously change (those present in the options)
so even if i send an ajax call to the server in order to pull an encrypted id corresponding to the item being altered in the form like this:
query by corresponding encrypted curso_edit id/value, encrypted trienio_edit id/value, unique email
the user can inspect the javascript code, replace the encrypted curso_edit, trienio_edit value, and e-mail by another one present in the options above.
how can i fix this ?
p.s - dont be too harsh on me. this problem is somewhat difficult to explain and i've tried my best to explain it, if you need more details say
by the way: i've organized the model by id, id cartao, nome, email and by using relationships, trienio and curso. this is somewhat a school management system, and by virtue of that, anybody that knows this info: course (curso), year (trienio), card id (id cartao, those are school cards with an id on it) ,name (nome) and email of a student will easily guess the columns values. i need something stronger and unguessable. and considering a school environment, those informations are very easily obtainable
I have a search feature built into a page that hits an API to get a list of items if a user chooses to search instead of manually enter (in an attempt to get some clean data). I have the first column of said table set to call a JavaScript function onclick. That function looks similar to this:
function loadDataFromTable(fname, lname, mname, stn, grade, school) {
$('#StudentFirstName').val(fname);
$('#StudentLastName').val(lname);
if (mname !== "undefined") {
$('#StudentMiddleName').val(mname);
}
else {
$('#StudentMiddleName').val('');
}
$('#StudentNumber').val(stn);
$('#Grade').val(grade);
$('#School').val(school);
return false;
}
The associated HTML elements are all ASP.NET Core Razor View input elements. They look like this:
<div class="form-group">
<label class="col-md-3 control-label">Last Name</label>
<div class="col-md-9">
<input type="text" asp-for="StudentLastName" class="form-control" />
<span asp-validation-for="StudentLastName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">STN</label>
<div class="col-md-9">
<input type="text" asp-for="StudentNumber" class="form-control" />
<span asp-validation-for="StudentNumber" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">Grade</label>
<div class="col-md-9">
<input type="text" asp-for="Grade" class="form-control" />
<span asp-validation-for="Grade" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="School" class="col-md-3 control-label"></label>
<div class="col-md-9">
<select asp-for="School" asp-items="ViewBag.SchoolList" class="form-control"></select>
<span asp-validation-for="School" class="text-danger"></span>
</div>
</div>
Now, if a user clicks on one of the links from the table, all of the values are properly passed into the function, and all of the values for First Name, Last Name, Middle Name, and STN properly update on the view. Grade and School do not update on the View, but their value attribute does update. When I submit the form after the data fills, the correct values are passed to my controller.
What I can't figure out is why the Grade and School values are not populating on the view. The only thing that stands out as different for these two are within the model they are nullable integers, whereas other fields are strings.
I have tried a mixture of .attr('value', grade), .text(grade), and .val(grade), and none of them are working. I can verify that the proper elements are being selected because if I output $('#Grade') I get the input object.
Please refer below link
https://plnkr.co/edit/9HbLMBUw0Q6mj7oyCahP?p=preview
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.NDCarray = [{val: ''}];
$scope.NDCadd = function() {
$scope.NDCarray.unshift(
{val: ''}
);
};
$scope.data = angular.copy($scope.NDCarray);
$scope.NDCcancel=function(){debugger
$scope.NDCarray=$scope.data;
}
$scope.NDCdelete = function(index) {
if(index != $scope.NDCarray.length -1){
$scope.NDCarray.splice(index, 1);
}
};
});
It contains the textbox with add button. I have added validation for number and required field, it is working fine. but when i click add button it will create another textbox with entered value that time it showing the validation message for all the textboxes , i don't want to show validation message for all the textboxes. need to show validation for corresponding textbox only. that means when i enter something wrong in second textbox it is showing message to that textbox only.refer below screenshot.
validation message displaying for all textboxes.that should display for only one textbox.
Working plnkr : https://plnkr.co/edit/f4kAdZSIsxWECd0i8LDT?p=preview
Your problem is in your HTML, to get independant fields you must :
Move outside the form of the ng-repeat
Provide a dynamic name using $index on your fields, because name is what make each fields independant on the validation.
Here is the final HTML from the plnkr i didn't touch at all the javascript :
<body ng-controller="MainCtrl">
<form name="myForm">
<div ng-repeat ="ndc in NDCarray">
<div class="col-sm-4 type7" style="font-size:14px;">
<div style="margin-bottom:5px;">NDC9</div>
<label>Number:
<input type="number" ng-model="ndc.value"
min="0" max="99" name="{{'input_'+$index}}" required>
</label>
<div role="alert">
<span class="error" ng-show="myForm.input.$dirty && myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.number">
Not valid number!</span>
</div>
<tt>value = {{example.value}}</tt><br/>
<tt>myForm['input_{{$index}}'].$valid = {{myForm['input_'+$index].$valid}}</tt><br/>
<tt>myForm['input_{{$index}}'].$error = {{myForm['input_'+$index].$error}}</tt><br/>
</div>
<div class="col-sm-4 type7 " style="font-size:14px;">
<div style="padding-top:20px; display:block">
<span class="red" id="delete" ng-class="{'disabled' : 'true'}" ng-click="NDCdelete($index)">Delete</span>
<span>Cancel </span>
<span id="addRow" style="cursor:pointer" ng-click="NDCadd()">Add </span>
</div>
</div>
</div>
<tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
</form>
</body>
Couple of changes:
If you add "track by $index" to your ng-repeat it will make each group of elements unique so that you don't have to worry about deriving unique names for elements.
Your validation on the number (myForm.ndcValue.$error.number) didn't work so I changed it to myForm.ndcValue.$error.max || myForm.ndcValue.$error.min
Also, you can throw an ng-form attribute directly on the div with your ng-repeat.
Like this:
<div ng-repeat="ndc in NDCarray track by $index" ng-form="myForm">
<div class="col-sm-4 type7" style="font-size:14px;">
<div style="margin-bottom:5px;">NDC9</div>
<label>Number:
<input type="number" ng-model="ndc.value" min="0" max="99" name="ndcValue" required>
</label>
<div role="alert">
<span class="error" ng-show="myForm.ndcValue.$dirty && myForm.ndcValue.$error.required">
Required!</span>
<span class="error" ng-show="myForm.ndcValue.$error.max || myForm.ndcValue.$error.min">
Not valid number!</span>
</div>
<tt>value = {{example.value}}</tt>
<br/>
<tt>myForm.ndcValue.$valid = {{myForm.ndcValue.$valid}}</tt>
<br/>
<tt>myForm.ndcValue.$error = {{myForm.ndcValue.$error}}</tt>
<br/>
</div>
Here's the working plunker.
I changed the input element name from "input" to "ndcValue" to be less confusing.