I made a simple function to handle update actions for user. A simple form that look like this
<div class="com-md-12 col-sm-12 no-pad no-margine" ng-controller="ProfileCtrl" ng-init="getProfile('{{$safeID}}')">
{!! Form::open(array('class' => 'form-horizontal signup-form', 'ng-submit' => 'updateProfile($event)')) !!}
<div class="form-group">
<div class="col-md-6 col-sm-6">
{!! Form::text('first_name', old('first_name'), array('class' => 'form-control', 'placeholder' => 'First Name*', 'ng-model' => 'uProfile.first_name')); !!}
{!! MessagerService::setInlineError($errors->first('first_name')) !!}
</div>
<div class="col-md-6 col-sm-6">
{!! Form::text('last_name', old('last_name'), array('class' => 'form-control', 'placeholder' => 'Last Name*', 'ng-model' => 'uProfile.last_name')); !!}
{!! MessagerService::setInlineError($errors->first('last_name')) !!}
</div>
</div>
<div class="form-group">
<div class="col-md-12 col-sm-12">
{!! Form::text('username', old('username'), array('class' => 'form-control', 'placeholder' => 'Screen Name*', 'ng-model' => 'uProfile.username')); !!}
{!! MessagerService::setInlineError($errors->first('username')) !!}
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-sm-6">
{!! Form::text('dob', old('dob'), array('class' => 'form-control', 'id' => 'dob', 'placeholder' => 'Date of Birth*', 'ng-model' => 'uProfile.dob')); !!}
{!! MessagerService::setInlineError($errors->first('dob')) !!}
</div>
<div class="col-md-6 col-sm-6">
{!! Form::select('gender', ['' => '------ Gender ------', 'male' => 'Male', 'female' => 'Female'], old('gender'),
array('class' => 'form-control', 'ng-model' => 'uProfile.gender')) !!}
{!! MessagerService::setInlineError($errors->first('gender')) !!}
</div>
</div>
<div class="form-group">
<div class="col-md-12 col-sm-12">
<div class="input-group">
<span class="input-group-addon" id="p_url_pretext">example.com/</span>
{!! Form::text('profile_url', old('profile_url'), array('class' => 'form-control', 'placeholder' => 'Profile URL*', 'ng-model' => 'uProfile.profile_url')); !!}
</div>
{!! MessagerService::setInlineError($errors->first('profile_url')) !!}
</div>
</div>
<div class="form-group">
<div class="col-md-12 col-sm-12">
<button type="submit" class="btn btn-default cbtn-login" style="float: right;">Save updates</button>
</div>
</div>
{!! Form::close() !!}
</div>
with angular script that look like this
$scope.updateProfile = function(event){
event.preventDefault();
$http({
method : 'POST',
url : svrid('www') + '/ws/profile/update',
data : $.param($scope.uProfile), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
}).success(function(data) {
console.log(data);
}).error(function(data) {
console.log(data);
});
};
Everything worked as i expected but I have noticed 1 weird behavior. Why are there so many unrecognized requests before my final POST action is being executed?
I noticed that supposed my action route is http://www.example.com:8000/ws/profile/update it somehow keeps on calling http://www.example.com:8000/ws/profile with 3 different requests POST, GET, and DELETE before it finally reaches the intended request as shown in image below
Anyone have any idea what causes such behavior to happen or have I coded something wrong in anywhere that leads to such incident?
Update 1: Here is the Plunkr file. Noted that i could not re-simulate the error because the site is currently at localhost
Update 2: I have narrowed down that the ng-init="getProfile('{{$safeID}}') might have been causing this problem. I tried removing that line and give it a constant value and the errors do not appear. What's with such behavior?
I have found out the problem that causes such behavior. It is mainly because of the jQuery's $.param function. What really happens is the $.param operation will run through all properties of you object. Using $.param as the object will not automatically convert to a url encoded string (though I think it should).
So what I as a workaround to this problem is create a manual serialization function like such
function serializeData( data ) {
// If this is not an object, defer to native stringification.
if ( ! angular.isObject( data ) ) {
return( ( data == null ) ? "" : data.toString() );
}
var buffer = [];
// Serialize each key in the object.
for ( var name in data ) {
if ( ! data.hasOwnProperty( name ) ) {
continue;
}
var value = data[ name ];
buffer.push(
encodeURIComponent( name ) + "=" + encodeURIComponent( ( value == null ) ? "" : value )
);
}
// Serialize the buffer and clean it up for transportation.
var source = buffer.join( "&" ).replace( /%20/g, "+" );
return( source );
}
pass the form payload to the serialization function then append it into angular's #http
$http({
method : 'POST',
url : svrid('www') + '/ws/profile/update',
data : serializeData($scope.uProfile), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
}).success(function(data) {
$scope.uError = null;
}).error(function(data) {
$scope.uError = data;
console.log(data);
});
and everything works like a charm.
Related
I have a multi-select option and i want to save all record in database, now it's saving only the last one, how can I do that? I need to save multi-select from tags with comma (,) between. .
Here is my controller and what I tried
$news = News::create([
'locale' => Session::get('admin_locale'),
'title' => $request['title'],
'slug' => Slugify::slugify($request['title']),
'news_class' => $request['news_class'],
'description' => $request['description'],
'tag' => $request['tag'],
'tags' => $request->input['tags'],
'category' => 'news',
'category_id' => $request['category_id'],
'metatitle' => $request['title'],
'metadescription' => substr(strip_tags($request['description']), 0, 160),
'image' => $image,
]);
Here is my view:
<div class="row d-flex justify-content-center mt-100 col-md-12 g-mb-30" >
<div class="col-md-12" >
<label class="g-mb-10">Tags</label>
<select id="choices-multiple-remove-button" placeholder="Select" multiple title="Category Talent" name="tags">
#foreach($news as $tag)
<option value="{{ $tag->tag }}">{{ $tag->tag }}</option>
#endforeach
</select> </div>
</div>
To pass multiple values you probably want to rename your input to be an array:
<select ... name="tags[]">
Then on the server side you should receive them as an array under the input tags:
$tags = $request->input('tags', []);
You can join the array elements with implode to get a string representation:
$tags = implode(',', $tags);
PHP Manual - Function Reference - Text Processing - Strings - Functions - implode
$news = News::create([
...
'tags' => implode(',', $request->input('tags', [])),
...
]);
Please help me. How save data from form? If its standard from, everything works, but my code for form is:
{!! Form::open(['url' => 'fill2', 'method' => 'post', 'class' => 'result', ]) !!}
#forelse ($quests as $quest)
#if($post->form_id == $quest->form_id)
<blockquote class="blockquote bq-success">
<p class="bq-title"></p>
<p>{{$quest->quest_name}}</p>
<div class="d-flex flex-column">
#foreach($responses as $response)
#if($quest->quest_id == $response->quest_id)
<table>
<tr>
<th>
<input type="{{$response->response_type}}" name="{{$response->id}}"></th>
<th><label class="radio-inline">{{$response->response}}</label></th>
</tr>
</table>
#endif
#endforeach
<small>{{notempty ($quest->quest_note)}}</small>
</div>
</blockquote>
#endif
#empty
#endforelse
{!! Form::button('Send', ['type' => 'submit', 'class' => 'btn btn-primary']) !!}
{!! Form::close() !!}
And my code in controller is
$result = Auth::user()->results()->create($request->all() ?: []);
return $result->toArray();
And result:
{"user_id":4,"id":20} - only this is saving to database
I have maybe 30 checkboxs, but anything no save to database, and no send to post request. Any idea?
I am working on a registration form in symfony2 with angular js.
My doubt is can we do angular js validations in a symfony2 form?
because i cannot validate the form and also i dont know how to post form values to symfony controller..
please help..
I am stuck in project..
please check my registration.html.twig code..
<body ng-app="LoginApp">
<div id="register" class="animate form" ng-controller="RegisterController as registerCtrl">
{{ form_start(form, {'attr': {'name':'registerFrm', 'id':'registerFrmId','novalidate': '', 'ng-submit':'registerCtrl.registerFrm()'}}) }}
Your username
{{ form_row(form.username) }}
<span class="error" ng-show="submitted && registerFrm.adminuser[username].$error.required">Username is required!</span>
Your email
{{ form_row(form.email) }}
<span class="error" ng-show="submitted && registerFrm.adminuser[email].$invalid">Invalid email</span>
Your password
{{ form_row(form.plainPassword.first) }}
<span class="error" ng-show="submitted && registerFrm.adminuser[plainPassword][first].$error.required">Password is required!</span>
Please confirm your password
{{ form_row(form.plainPassword.second) }}
<span class="error" ng-show="submitted && registerFrm.adminuser[plainPassword][second].$error.required">Password is required!</span>
<p class="signin button">
<input type="submit" name="signup" ng-model="signup" ng-click="submitted=true" value="Sign up" />
</p>
{{ form_end(form) }}
</div>
<script>
var App = angular.module('LoginApp',[]);
App.controller('RegisterController', ['$scope',function($scope) {
}]);
</script>
</body>
My symfony form builder
$builder
->add('username', TextType::class , array(
'label' => false,
'attr' => array(
'ng-model' => 'formData.username',
'id' => 'usernamesignup',
'placeholder' => 'myusername690',
'required' => false)
))
->add('email', TextType::class , array(
'label' => false,
'attr' => array(
'ng-model' => 'formData.email',
'id' => 'emailsignup',
'placeholder' => 'mymail#mail.com',
'ng-pattern' => '/^([0-9a-zA-Z]([-\.\w]*[0-9a-zA-Z])*#([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/',
'required' => false)
))
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options' => array(
'label' => false,
'attr' => array(
'ng-model' => 'formData.password',
'id' => 'passwordsignup',
'placeholder' => 'eg. X8df!90EO',
'required' => false)
),
'second_options' => array('label' => false,
'attr' => array(
'ng-model' => 'formData.confirm_password',
'id' => 'passwordsignup_confirm',
'placeholder' => 'eg. X8df!90EO',
'required' => false)
),
)
);
registration form image
Hey Dmitry Grachikov,
Please change your code
<span class="error" ng-show="submitted && registerFrm.adminuser[username].$error.required">Username is required!</span>
to
<span class="error" ng-show="submitted && registerFrm['adminuser[username]'].$error.required">Username is required!</span>
Your code having syntactic JS error.
If you want to reference a property named adminuser[username], you should do it like this:
registerFrm['adminuser[username]'].$error
registerFrm.adminuser[username] is incorrectly interpreted as (registerFrm.adminuser)[username]
The easiest ways there is to render your form in twig just to get html of a form with field names. Afterwards you have to use exactly the same field names in form submit request and symfony forms component will handle it.
I am using cakephp 2.6.7:
I have a password reset url like:
http://www.jegeachi.com/resellers/resetpw/9610f4e33d96ad6189c5a779ab90f10aBXX1066056669XXB12/
Here resellers is the controller and resetpw is the action and 9610f4e33d96ad6189c5a779ab90f10aBXX1066056669XXB12 is the argument I want to pass into resetpw function.
Now in resetpw.ctp:
<style type="text/css">
.alert {
padding: 6px;
margin-bottom: 5px;
border: 1px solid transparent;
border-radius: 4px;
text-align: center;
}
.alert.alert-error {
background: #A9B0B5;
color: #EF5858;
font-weight: normal;
}
</style>
<div class="page-content-wrapper">
<div class="page-content">
<!-- BEGIN PAGE CONTENT-->
<div class="content">
<!-- BEGIN LOGIN FORM -->
<?php
echo $this->Form->create('Reseller', array(
'inputDefaults' => array(
'label' => false,
'div' => false
),
'class' => 'login-form',
'url' => array('controller' => 'resellers', 'action' => 'resetpw')
)
);
?>
<h3 class="form-title">Type your new password</h3>
<div class="alert alert-danger display-hide">
<button class="close" data-close="alert"></button>
<span>
Enter your new password first. </span>
</div>
<div class="form-group">
<label class="control-label visible-ie8 visible-ie9">New Password</label>
<div class="input-icon">
<i class="fa fa-lock"></i>
<?php
echo $this->Form->input(
'password', array(
'class' => 'form-control placeholder-no-fix',
'type' => 'password',
'autocomplete' => 'off',
'placeholder' => 'New Password'
)
);
?>
</div>
</div>
<div class="form-actions">
<?php
echo $this->Form->button(
'Reset Password <i class="m-icon-swapright m-icon-white"></i>', array(
'class' => 'btn blue pull-right',
'type' => 'submit',
'escape' => false
)
);
?>
</div>
<?php echo $this->Form->end(); ?>
<!-- END LOGIN FORM -->
</div>
<!-- END PAGE CONTENT -->
</div>
</div>
<!-- END CONTENT -->
Inside resellers action:
function resetpw($a){
$this->layout = "public-login";
$this->loadModel('Reseller');
if ($this->request->is('post')) {
echo 'a : '.$a;
pr($this->params['url']); exit;
$a = func_get_args();
$keyPair = $a[0];
$key = explode('BXX', $keyPair);
$pair = explode('XXB',$key[1]);
$key = $key[0];
$pair = $pair[1];
$password = $this->request->data['Reseller']['password'];
unset($this->request->data['Reseller']['password']);
$uArr = $this->Reseller->findById($pair);
if($uArr['Reseller']['resetkey'] == $key) {
$this->Reseller->read(null, $pair);
$this->Reseller->set('password', $password);
if($this->Reseller->save()) {
$msg = ' <div class="alert alert-success">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>Your password has been reset</strong>
</div>';
} else {
$msg = ' <div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">×</button>
Something has gone wrong. Please try later or <strong>sign up again</strong>
</div>';
}
} else {
$msg = ' <div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>Invalid link.Please check your reset link</strong> Invalid link.Please check your reset link
</div>';
}
$this->Session->setFlash($msg);
$this->redirect(array('controller'=>'resellers', 'action' => 'login'));
}
}
Here I want to catch the url data 9610f4e33d96ad6189c5a779ab90f10aBXX1066056669XXB12
But none of the following printing my data:
echo 'a : '.$a;
pr($this->params['url']); exit;
How can I get this url value.
As I said in one of my comments on your previous questions, you should first read the docs. What you are doing in this action is wrong on couple of levels, in cakephp sense. Normally you would get to this action by url I suppose
.../resellers/resetpw/9610f4e33d96ad6189c5a779ab90f10aBXX1066056669XXB12/
and by that you would already have that action argument in your controller:
public function resetpw($a = null)
Then you would check if $a is not null since you can't reset password without some kind of token. In your action $a already has this for value 9610f4e33d96ad6189c5a779ab90f10aBXX1066056669XXB12.
No need to use something like this:
$a = func_get_args();
Second thing, you should name arguments to be meaningful, $a doesn't mean nothing, but $token or something similar would make much difference.
There are multiple ways of doing it. In your function below (not writing entire one) you are trying to get the url argument in $a but you are passing parameter instead. Hence $a has no value
function resetpw($a){
$this->layout = "public-login";
$this->loadModel('Reseller');
if ($this->request->is('post')) {
echo 'a : '.$a; //$a will have no values here
pr($this->params['url']); exit;
In your case you need catch params like below
$a = $this->params['passed'][0];
Or to get argument your URL should be like below
http://www.jegeachi.com/resellers/resetpw?9610f4e33d96ad6189c5a779ab90f10aBXX1066056669XXB12/
so that you can collect it in $a. Hope this helps to you!
I solved this by removing 'url' in Form.
I changed
<?php
echo $this->Form->create('Reseller', array(
'inputDefaults' => array(
'label' => false,
'div' => false
),
'class' => 'login-form',
'url' => array('controller' => 'resellers', 'action' => 'resetpw')
)
);
?>
To
<?php
echo $this->Form->create('Reseller', array(
'inputDefaults' => array(
'label' => false,
'div' => false
),
'class' => 'login-form',
)
);
?>
Now it works. When you set url then parameter in url is removed.
I am using a Form helper in CakePHP. like
echo $form->input('field', array(
'type' => 'radio','legend'=>$r['Attribute']['label'],
// 'after' => '--after--',
// 'between' => '--between---',
'separator' => '--separator--',
'options' => array('1', '2')
));
which generates me as
<div class="input radio">
<fieldset>
<legend>Gender</legend>
<input type="hidden" value="" id="field_" name="data[field]"/>
<input type="radio" value="0" id="Field0" name="data[field]"/>
<label for="Field0">1</label>--separator--
<input type="radio" value="1" id="Field1" name="data[field]"/>
<label for="Field1">2</label>
</fieldset>
</div>
Is there any way to keep my options that i have received from my Database instead of 1,2
where i tried it with receving my options using
<?php foreach ($viewfields as $r): ?>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready(function($){
$("#"+<?=$r['Attribute']['id'];?>).each(function() {
type= "<?=$r['Attribute']['type'];?>";
if(type=="radio")
{
var ht = $.ajax({
type: "GET",
url: "http://localhost/FormBuilder/index.php/forms/viewChoices/"+attribute_id,
async: false
}).responseText;
var myObject = eval('(' + ht + ')');
var data = myObject;var j=0;
$.map(data.choices, function(i){ j++;
alert(i.choice);//which alerts as male and female correctly.
return i.choice;});
}
});//each
});
alert(i.choice); alerts the options correctly ..
How to keep these options in the array() of the Form Helper so that to get these options male and female instead of default 1,2
Please suggest me..
Place the options in a key => value array - as shown here : Cake Options
echo $form->input('field', array(
'type' => 'radio',
'legend' => $r['Attribute']['label'],
'separator' => '--separator--',
'options' => array('Male' => 'male', 'Female' => 'female')
));
See how you go.