Toggle Value in Angular Material CheckBox - angular-material2

I have a Template Driven Form in which i am putting a checkbox that can toggle its value.
Component
public toggles = [
{ value: 'toggled', display: 'Toggled' },
{ value: 'untoggled', display: 'UnToggled' },
];
<div>
<input type="hidden" name="toggle" [(ngModel)]="user.toggle">
<div>
<label>
<input type="checkbox"
[checked]="user.toggle === toggles[0].value"
(change)="$event.target.checked? (user.toggle = toggles[0].value) : (user.toggle = toggles[1].value)">
{{ toggles[0].display }}
</label>
</div>
</div>
The following works great, but when i am switching to Angular Material it just fails to works .
The material Template code
<input type="hidden" name="toggle" [(ngModel)]="user.toggle">
<md-checkbox [checked]="user.toggle === toggles[0].value"
(change)="$event.target.checked?(user.toggle = toggles[0].value): (user.toggle = toggles[1].value)">
{{toggles[0].display}}</md-checkbox>
I am getting the following Error in console, it says cannot read the property of undefined console,
TypeError: Cannot read property 'checked' of undefined
at Object.eval [as handleEvent] (TemplateDrivenComponent.html:64)
I know the point where the error is occurring $event.target.checked angular cannot read this checked event on md-checkbox , how to get around this any pointers will be great
thanks

Looking at comments try the following hope this solves the issue i guess you need not use target with event in Material.
<input type="hidden" name="toggle" [(ngModel)]="user.toggle">
<md-checkbox [checked]="user.toggle === toggles[0].value"
(change)="$event.checked?(user.toggle = toggles[0].value): (user.toggle = toggles[1].value)">
{{toggles[0].display}}</md-checkbox>

Related

What is this.loading = false?

I am using Laravel and Vue.
When I was searching on the internet I saw the following code.
<template>
<div>
<h3 class="text-center">Create Movie</h3>
<div class="row">
<div class="col-md-6">
<form #submit.prevent="createMovie">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" v-model="movie.name">
</div>
<div class="form-group">
<label>Director</label>
<input type="text" class="form-control" v-model="movie.director">
</div>
<button type="submit" class="btn btn-primary">Create movie</button>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
movie: {}
}
},
methods: {
createMovie() {
this.axios
.post('http://localhost:8000/api/movie/create', this.movie)
.then(response => (
this.$router.push({name: 'movie'})
))
.catch(error => console.log(error))
.finally(() => this.loading = false)
}
}
}
I am trying to find out what the last line
.finally(() => this.loading = false)
is doing. I am searching on the internet but I can't find what it does. Also, I tried running the code without the last line however, it did not make any change.
Can someone please tell me what this is doing and when it is useful?
Without seeing the associated Vue template we cannot explain what it is doing exactly, however, we can be fairly confident that the value of loading will be used to show/hide some sort of overlay or activity spinner.
The purpose of the overlay/activity spinner is to provide visual feedback to the user that something is happening. This is useful when loading large amounts of data into your page, or when you perform a long running process (such as uploading a large file for example). So rather than the user seeing nothing on first page load, or clicking a button and wondering if it worked, they are provided with something to let them know that something is happening.
A basic example of what this might look like in the Vue template could be:
// if the value of loading is true, show this
<div v-if="this.loading">Loading, please wait ...</div>
// otherwise show this
<div v-else>Other content</div>
Your example is setting the value of loading to false once a response has been received from your axios request. You would probably want to set the value of loading to true prior to making the request to show an overlay/activity spinner.
Uncaught (in promise) ReferenceError: ture is not defined
You have a typo, it should be true not ture.

In Laravel 5.7 app make validation with tinyMCE editor

In my Laravel 5.7 application I use laravel-jsvalidation plugin( https://github.com/proengsoft/laravel-jsvalidation/wiki/Basic-Usage )
and it worked ok,
I needed to including textarea input as tinyMCE editor and to use i with validation and I implemented it with 2 textarea inputs :
<div class="form-row mb-3 {{ in_array('description', $errorFieldsArray) ? 'validation_error' : '' }}">
<label class="col-xs-12 col-sm-4 col-form-label">Description</label>
<div class="col-xs-12 col-sm-8">
<span style="display: inline;">
{{ Form::textarea('description', isset($vote->description) ? $vote->description : '', [ "class"=>"form-control editable_field textarea_input ", "rows"=>"0", "cols"=> 120, "id"=>"description", "autocomplete"=>"off", "style"=>"width:0; height:0" ] ) }}
</span>
{{ Form::textarea('description_container', isset($vote->description) ? $vote->description : '', [ "class"=>"form-control editable_field textarea_input ", "rows"=>"5", "cols"=> 120, "id"=>"description_container", "autocomplete"=>"off" ] ) }}
</div>
</div>
where 1st textarea is for form submitting, as entered content is copied into it from 2nd textarea, which is used as
tinyMCE editor.
In tinyMCE definition I added rows:
setup: function (editor) {
editor.on('change', function () {
var current_context= tinymce.get(by_selector_container).getContent()
$('#' + by_selector).html( current_context );
});
},
where by_selector_container and by_selector are names of these textarea inputs. It works, but the only problem that on page I can see 1st textarea input,
despite I try to hide it setting wight/height in 0 in style of my code above, but anyway I still see small textarea input : https://imgur.com/a/43FRFJU
I tried in declaration of the 1st textarea input to set
"style"=>"display:none"
Than textarea input was hidden but validation does not work at all.
How to hide it this small textarea input with validation working?
Thanks!
You can try style:
visibility: hidden ;

Server side validation for angular 2 forms

I am trying to figure out how I can send some data to a server side API call, let that do the validation and then return back with some validation errors and those validation errors should be displayed along with the component that caused the validation error. Here is how my data model looks like:
export class Order {
orderNo: string;
items: Item[];
constructor() {
this.items = [];
}
}
export class Item {
recNo: string;
}
This is how the HTML form looks like
<div class="form-group">
<label name="orderNo">Order Number</label>
<input type="text" formControlName="orderNo" />
</div>
<div formArrayName="items">
<div *ngFor="let item of orderForm.controls.items.controls; let i=index" [formGroupName]="i">
<div class="form-group">
<label>Item # {{i}}</label>
<input type="text" formControlName="recNo" />
</div>
</div>
</div>
The validation errors that I receive from the server are in this form
[
{
"field": "orderNo",
"message": "order number is required"
},
{
"field": "items[2].recNo",
"message": "record number is required"
}
]
I am not able to figure out how, once I receive the validation errors, can I update the errors objects on the form controls or populate some other structure to show the errors. Its a bit simpler for static fields like orderNo but a lot more complex for nested array fields like items[0].recNo to update the errors programmatically. Any ideas would be appreciated.
This is what I ended up doing:
<div class="form-group" [class.has-danger]="!ctrl.valid && ctrl.enabled">
<input type="text" class="form-control" [formControl]="ctrl"
value="{{valueFormatter(ctrl)}}"
[class.form-control-danger]="!ctrl.valid && ctrl.enabled"
[ngbTooltip]="ctrl.errors ? ctrl.errors.e : falsy" />
</div>
Basically, setting up error classes on the form control based on the ctrl valid/error state and here is an example of specifying an error on a control:
this.ctrl.setErrors({ "e": this.label + " is required"});
I just used a predefined error key e to display any errors. This way, once I receive the error list from the backend, I can set the e error on a control and have that show up in a tooltip on the control.

Showing a system error on a form after submitting via AJAX

I'm trying to find the best way in Angular to invalidate a form not due to a specific element, but due to a system-level error AFTER submission via AJAX. For example, you could put in a valid email and password (both good strings), press submit, and find out there is a system error that should trigger a generic error message on the form. Since this isn't tied to anything in the data model, what is the best way I can generically call the form 'invalid'?
<form name="loginForm" class="loginForm" ng-submit="loginSubmit(loginForm)">
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email" ng-model="login.email" required>
<span class="error" ng-show="loginSubmit.email.$error">Required!</span><br>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password" ng-model="login.password" minlength="8" required>
</div>
<button type="submit" class="btn btn-default">Log In</button>
</form>
and...
ngModule.controller('LoginController', function($scope, $location) {
$scope['login'] = {};
$scope['loginSubmit'] = function(form) {
var loginPromise = myAsyncLoginFuncYouCanAssumeWorks();
loginPromise.done(function(){
$location.path('/');
});
loginPromise.fail(function() {
//how best to trigger a generic error in the form here?
});
};
});
As you can see, I'd like to trigger some form-wide error state after submission. It really could be as simple as adding an invalid form class to the form, but again, I'd like to know the purest Angular way to do this.
Add a label to your form with your generic error which shows upon a scope variable being true when an error occurs:
<div class="alert alert-danger" role="alert" ng-show="loginError">There was an error with your login details. Please check them and try again</div>
then when your promise fails:
loginPromise.fail(function () {
$scope.loginError = true;
});
maybe also could be nice if you have many system messages to abstract them all out into a separate service so you can inject the systemmessages service into your controller and then simply bind:
<div class="alert alert-danger" role="alert" ng-show="loginError">{{ systemMessages.loginError }}</div>
Alternatively as you use Bootstrap maybe inject the $modal service and show the error message inside a popup.
It is also important to make sure you try to use a bearer token stored in localatorage as oppose to cookies for persistence, so it doesn't get sent to the server on each request.
Anti forgery token would also be very beneficial for SPAs.
Your server could return some sort or error pay load with error key or error code.
{errors:[{key:"invalid.password"}]}
Assign the error response to your scope:
loginPromise.fail(function(response) {
$scope.errors = response.data;
});
Next, add filter to translate error key/code into error messages:
angular.module('mtApp').filter('errorFilter', function() {
return function(e) {
if (e === 'invalid.password') {
return 'Invalid password, please try again.';
}
};
});
Finally, display the appropriated errors as a list:
<div ng-show="errors">
<ul>
<li ng-repeat="e in errors">{{e.key | errorFilter}}</li>
</ul>
</div>
Optionally, you can reuse this same "$scope.erros" object combined to ng-class and control the CSS of each field with error.

Hot Towel Angular data-ng-show not working during validation

Hello anyone has anyone tried doing a validation using angularjs in a with Hot Towel template?
Basically i have a property in my angular controller which is binded(two way) in my view.
I just want to do a simple required validation, and then show a <span> element with the message.
here is my controller code
(function () {
'use strict';
var controllerId = 'login';
angular.module('app').controller(controllerId, ['$scope', 'common', 'userservice','$location', login]);
function login($scope, common, userservice, $location) {
var getLogFn = common.logger.getLogFn;
var log = getLogFn(controllerId);
var vm = this;
vm.title = 'Login';
//view model for credentials
vm.email = null;
activate();
function activate() {
common.activateController([], controllerId)
.then(function () { log('Activated Login View'); });
}
}
})();
and this is my view
<div data-ng-controller="login as vm">
<form name="loginform" id="loginform" novalidate data-ng-submit="loginuser()">
<fieldset>
<legend>Login</legend>
<p>
<label>Email</label>
<input type="email" data-ng-model="email" placeholder="Email" required />
<span data-ng-show="loginform.email.$error.required">*</span>
</p>
</fieldset>
</form>
</div>
i dont know what the problem is, but the <span> just wont show. am i missing something?
You have to set 'name' attribute to your input email :
<input type="email" name="email" data-ng-model="email" placeholder="Email" required />
For each field of your form, angularjs will set a value like: loginform[name-attribute].
For your information, your span will be visible only when required error is triggered (when your email is not empty, your span will be hidden).
[EDIT] See this fiddle: http://jsfiddle.net/k82at

Resources