How to update password using angularjs and rails/devise? - ruby-on-rails

I'm having a problem trying to update a users password using a simple form with old and new password. The problem is I post {"user[current_password]":$scope.user.password,"user[password]":$scope.user.newpassword} data to my Devise::RegistrationsController and I get a simple 422 Unprocessable Entity response. Where am I going wrong?
This is my html
<div ng-controller="PasswordCtrl">
<form id="password-card" class="row" style="display:none;" name="password_form" ng-submit="changePassword()" novalidate>
<div class="span5">
<div class="form-inputs">
<label for="nPass"><%= I18n.t("registration.edit.current_password") %></label>
<input name="uPass" class="required" type="password" ng-model="user.password" required >
<div ng-show="password_form.uPass.$dirty && password_form.uPass.$invalid">Missing:
<span ng-show="password_form.uPass.$error.required">You must provided your current password.</span>
</div>
<label for="nPass"><%= I18n.t("registration.edit.new_password") %></label>
<input name="nPass" class="required" type="password" ng-model="user.newpassword" required >
<div ng-show="password_form.nPass.$dirty && password_form.nPass.$invalid">Missing:
<span ng-show="password_form.nPass.$error.required">Tell us your new password.</span>
</div>
<button id="x" type="submit" ng-disabled="!password_form.$valid" class="button secondary prefix">Breyta</button>
</div>
</div>
</form>
</div>
This is my angular controller
var PasswordCtrl=function($scope,registrationService, $http){
$scope.changePassword=function(){
console.log("current_password",password_form.uPass.value);
$http({
method: 'PUT',
url: '/skraning.json',
headers: {'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')},
data: {"user[current_password]":$scope.user.password,"user[password]":$scope.user.newpassword}
}).
success(function(data, status, headers, config) {
console.log("done",data);
});
};
};

your data object passed is not valid( user[current_password] & user[password]) : try like this with quotes
data: {"user['current_password']":$scope.user.password,"user['password']":$scope.user.newpassword}

Related

Devise params auto adds weird data in sign up registration controller

My application using vue3 to build devise sign up page and i'm using axios request to create user.
In registration controller, i found that params has added added an extra field name called registration data.
<ActionController::Parameters {"user"=>{"name"=>"name", "email"=>"mail", "phone"=>"123", "type"=>0}, "controller"=>"users/registrations", "action"=>"create", "registration"=>{"user"=>{"name"=>"name", "email"=>"mail", "phone"=>"123", "type"=>0}}}
It contains params[:user], that looks weird to me. Can someone explain?
"registration"=>{"user"=>{"name"=>"name", "email"=>"mail", "phone"=>"123", "type"=>0}
My form code:
methods: {
signUp: function(e) {
e.preventDefault();
let user_params = {
user: {
name: this.name,
email: this.email,
phone: this.phone,
type: this.type,
}
}
this.$http.post('/users', user_params)
.then(response => {
this.$emit('next');
}).catch(err => {
this.error = err.response.data;
});
},
}
And in view
<form>
<div class="col-md-6 col-sm-8 col-10 mt-5 mx-auto text-center">
<div class="checked-circle mx-auto">
<img :src="checkedStepImg" class="w-100 h-100">
</div>
<div class="title mt-5"> Let sign up for your account </div>
<div class="mt-3 text-red" v-if="error">{{ error }} </div>
<div class="row mt-3">
<div class="col-6">
<input class="form-control shadow-none rounded-0" placeholder="Name" v-model="name">
</div>
<div class="col-6">
<input class="form-control shadow-none rounded-0" placeholder="Email" v-model="email">
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<div class="input-group">
<span class="input-group-text rounded-0">+1</span>
<input type="text" class="form-control shadow-none rounded-0 bg-white" placeholder="Phone" v-model="phone">
</div>
</div>
<div class="col-6">
<select class="form-select shadow-none rounded-0" aria-label="Default select example" v-model="type">
<option value="0" selected> Personal </option>
<option value="1"> Corporation </option>
</select>
</div>
</div>
<div class="col-6 col-sm-5 mx-auto btn-box mt-5">
<button class="btn btn-dark w-100 h-100" #click.prevent="signUp"> Sign up!</button>
</div>
</div>
</form>
That does not happen if i use a normal form devise sign_up

Get object from controller to view using ajax in .net mvc core

Controller:
[HttpGet]
public IActionResult Edit(int id)
{
Teacher teacher = teacherService.GetTeacherById(id);
EditTeacherData(teacher);
return View();
}
public JsonResult EditTeacherData( Teacher teacher)
{
return Json(teacher);
}
Ajax:
$.ajax({
type: "GET",
url: "/Teacher/EditTeacherData",
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (data) {
debugger;
console.log(data)
},
error: function (response) {
debugger;
alert('eror');
}
});
View:
#model StudentTeacher.Models.TeacherViewModel
#{
ViewData["Title"] = "EditTeacher";
}
<h1>EditTeacher</h1>
<h4>Teacher</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form id="AddTeacherForm">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="TeacherId" id="TeacherId" />
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" id="Name" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Designation" class="control-label"></label>
<input asp-for="Designation" class="form-control" id="Designation" />
<span asp-validation-for="Designation" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Education" class="control-label"></label>
<input asp-for="Education" class="form-control" id="Education" />
<span asp-validation-for="Education" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="JoiningDate" class="control-label"></label>
<input asp-for="JoiningDate" class="form-control" id="JoiningDate"/>
<span asp-validation-for="JoiningDate" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" id="Submit" />
</div>
</form>
</div>
</div>
teacherService is a service that retrieves data that match with id. But it return null object. When I use this EditTeacherData(teacher); ajax not return a null object But in debugger model show value takes this function. I just wanna get an object through ajax and show data in the field via ajax.
Obviously, there is no parameter passed in to the controller in your ajax, so Edit method will never receive the parameter passed in.
You can implement it with EF core. If you want to use ajax, you can refer to this.
You can also achieve it without ajax, it much easier, please refer to this.
You are not sending data from your ajax request. Please read this for clear understanding
$('#Submit').click(function(){
var formData = $('#AddTeacherForm').serialize();
$.ajax({
type: "GET",
url: "/Teacher/EditTeacherData",
data: formData,
success: function (data) {
debugger;
console.log(data)
},
error: function (response) {
debugger;
alert('eror');
}
});
})

Angular 7 Reactive Form returns previous entered value on Pressing Enter key

I have created a login form using angular reactive form. I've facing some strange behavior
If I submit the form using the submit button, I get the latest values which I've entered. If I submit the form using Enter key, then the value received is not latest. I've added the code below, can anyone pls suggest what i'm doing wrong.
ngOnInit() {
this.loginForm = this.formBuilder.group(
{
username: new FormControl(),
password: new FormControl(),
RememberMe: []
},
{
updateOn: 'blur'
}
);
}
login() {
const formvalue = this.loginForm.value;
console.log(formvalue);
return;
}
<div class="limiter">
<div class="container-login100 img-bg">
<div class="wrap-login100">
<img class="logo-center" src="../../../../assets/images/logo-big.png" />
<form [formGroup]="loginForm">
<div class="ui segment">
<h2>Login Form</h2>
<div class="ui form" >
<div class="required inline field">
<label>Username</label>
<div class="ui left icon input">
<i class="user icon"></i>
<input type="text" name="Username" placeholder="username" formControlName="username" >
</div>
</div>
<div class="required inline field">
<label>Password</label>
<div class="ui left icon input">
<i class="lock icon"></i>
<input [type]= "'password'" placeholder="password" formControlName="password" >
</div>
</div>
<div class="field login-ckeck">
<sui-checkbox>
Remember me
</sui-checkbox>
</div>
<button [ngClass]= "'ui primary button'" (click)= "login()">Submit</button> Forgot your password?
</div>
</div>
</form>
</div>
<!-- <footer class="footer">footer</footer> -->
</div>
</div>
Found the solution, it was an error from my side.
I had to change the updateOn to submit, for my code to work
this.loginForm = this.formBuilder.group(
{
username: new FormControl(),
password: new FormControl(),
RememberMe: []
},
{
updateOn: 'submit'
}
);
You can listen to either the forms (ngSubmit) or directly to the (keyup.enter) event and trigger the event then.
<form (ngSubmit)="login()">
<form (keyup.enter)="login()">

Form validations lost when included in template

I have a directive, which successfully includes a template in my AngularJS app using Rails 4.2 and angular-rails-templates.
Everything seems to be working fine, even the two way data binding, although there is one exception. Form validation using AngularJS is lost if I include the <form> tag inside the template file.
When I run this in my local environment, Angular includes the template, display it on my main page. if you enter data the two way data binding updates, but the form validation is not handled by Angular, it uses HTML5 browser validation instead.
Any help appreciated, I assume there is some common thing I am missing, like how / when the template is inserted?
I have prepared a working demo at Plnkr, the same code executes without incident on Plnkr, but not when using Rails.
JS:
var app = angular.module('app', ['templates']);
app.config([
'$httpProvider', function($httpProvider) {
return $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
}
]);
app.run(function() {
return console.log('angular app running');
});
app.directive('serviceRequest', function() {
return {
restrict: 'E',
templateUrl: 'service-request.html',
controller:function() {
this.request = {};
this.addService = function(request) {
//$http request
this.request = {};
}
},
controllerAs: 'service'
};
});
The HTML template (service-request.html):
<form name="myForm" novalidate="">
<div>
serviceForm is {{myForm.$valid}}
</div>
<fieldset>
<legend>Service Request</legend>
<h1>{{service.request.number}} <small>{{service.request.reported | date}}</small></h1>
<div class="row">
<div class="small-12 medium-10 large-10 small-centered">
<div class="row">
<div class="small-3 columns">
<label for="right-label" class="right">Number:</label>
</div>
<div class="small-9 columns">
<label>
<input type="text" ng-model="service.request.number" placeholder="small-9.columns" required/>
</label>
</div>
</div>
</div>
</div>
<div class="row">
<div class="small-12 medium-10 large-10 small-centered">
<div class="row">
<div class="small-3 columns">
<label for="right-label" class="right">Reported:</label>
</div>
<div class="small-9 columns">
<input type="text" ng-model="service.request.reported" placeholder="small-9.columns" required/>
</div>
</div>
</div>
</div>
<input type="submit" ng-disabled="myForm.$invalid ">
</fieldset>
</form>

Saving data through AngularJS

Update:
I have replaced <input type=submit to <button ... and also remove the form tag from my html, after modifying my code i do not see it executing my JS and I have a debugger line in the code and it does not break....
I'm trying to POST data and I have all the code in placed and wired-up correctly (I believe) but when I try to Submit my page # My page gets refreshed, I don't see any event is firing and I have set debugger in the JS, and I do not see any JS error in developer tool
What I'm missing here apart from my code?
here is my code:
//HML code
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My AngularJS App</title>
<script src="../AppScripts/RequesterAdd.js"></script>
</head>
<body>
<form>
<div ng-app="requesterAddModule" ng-controller="requesterAddController" class="container">
<h2> add requester</h2>
<div ng-show="ShowMessage">Record saved Successfully</div>
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>HostModel</h4>
<hr />
<div class="form-group">
<div>First Name:</div>
<div class="col-md-10">
<input type="text" ng-model="FirstName" required class="form-control input-lg" placeholder="First Name" />
</div>
</div>
<div class="form-group">
<div>Middle Name:</div>
<div class="col-md-10">
<input type="text" ng-model="MiddleName" required class="form-control input-lg" placeholder="Middle Name" />
</div>
</div>
<div class="form-group">
<div>Last Name:</div>
<div class="col-md-10">
<input type="text" ng-model="LastName" required class="form-control input-lg" placeholder="Last Name" />
</div>
</div>
<div class="form-group">
<div>eMail Address:</div>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
<input type="text" ng-model="Email" required class="form-control input-lg" placeholder="Email Address" />
</div>
</div>
<div class="form-group">
<div>Is Host Active:</div>
<div class="col-md-10">
<input type="checkbox" ng-model="Active" required class="control-label col-md-2" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" id="btnCreate" data-ng-click="addRequester_ClickEvent" value="Create" class="btn btn-primary" />
</div>
</div>
</div>
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</form>
</body>
</html>
//JS:
var requesterAddModule = angular.module("requesterAddModule", []);
requesterAddModule.factory('requesterAddService',
['$http', function ($http) {
return {
addRequester: function (reqesterData) {
console.log(reqesterData);
debugger;
$http({
url: 'PersistRequester',
method: 'POST',
data: reqesterData
}).then (function (response) {
if (response !== 'undefined' && typeof(response) == 'object') {
window.location.href = '/'
}
},
function(response) {
//failed
}
);
}
};
}]);
requesterAddModule.controller('requesterAddController', ['$scope', '$http', '$window', 'requesterAddService', function ($scope, $http, $window, requesterAddService) {
$scope.addRequester_ClickEvent = function () {
var req = {};
debugger;
req["FirstName"] = $scope.FirstName;
req["MiddleName"] = $scope.MiddleName;
req["LastName"] = $scope.LastName;
req["Email"] = $scope.Email;
req["Active"] = $scope.Active;
requesterAddService.addRequester(req);
}
}]);
//MVC Server side code:
[HttpPost]
public JsonResult PersistRequester(Requester requester)
{
var req = requester;
//if (ModelState.IsValid)
// {
req.CreatedDateTime = DateTime.Now;
db.Requesters.Add(requester);
db.SaveChanges();
return Json(new { Status = "Success" });
//}
}
You're using a form without a method and action which will by default post to the current url. I would highly recommend not to use a form or at least not using an <input type="submit" /> which will default in all the browsers to submit the form.
You're clearly using Bootstrap 3 here so why not just remove the form tag and the submit button and replace it with another element which will not trigger the form post and style it with class="btn btn-primary". Some could argue against this practise along the graceful degradation guidelines but since this particular form is not built from ground up to support the non-js scenario, it is best not to allow browser submit at all.
Also, in your service where you're doing the actual post, you specifically tell the page to reload.
if (response !== 'undefined' && typeof(response) == 'object') {
window.location.href = '/'
}
You should pass this data back to the viewmodel so that the view can re-render and display the response.
If you change the url, the view state is lost and the page will simply render again to the initial state.
instead line
<input type="submit" id="btnCreate" data-ng-click="addRequester_ClickEvent" value="Create" class="btn btn-primary" />
please do
<button id="btnCreate" data-ng-click="addRequester_ClickEvent()" class="btn btn-primary" >Create</button>
I've just tested and is working for me replace:
<input type="submit" id="btnCreate" data-ng-click="addRequester_ClickEvent" value="Create" class="btn btn-primary" />
with
<button id="btnCreate" data-ng-click="addRequester_ClickEvent()" value="Create" class="btn btn-primary" >submit</button>
and I've change a bit your service to :
requesterAddModule.factory('requesterAddService',
['$http', function ($http)
{
return {
addRequester: function (reqesterData)
{
console.log(reqesterData);
debugger;
$http.post('PersistRequester', reqesterData).then(function (response)
{
if (response !== 'undefined' && typeof (response) == 'object') {
window.location.href = '/'
}
},
function (response)
{
//failed
}
);
}
};
}]);
it's posting to /home/PersistRequester if method 'PersistRequester' exist in other controller ie : foo controller change
$http.post('PersistRequester', reqesterData).then(function (response)
to $http.post('foo/PersistRequester', reqesterData).then(function (response)

Resources