I have a modal that returns login view . I want to check if user does not exist return the view with some error . I tried using
ModelState.AddModelError()
But the modal close and view is opened.
this is my code:
public IActionResult Login(LoginViewModel login)
{
if (!ModelState.IsValid)
return View();
var user = _userServies.getUserByEmailandPass(login.Email, login.Password);
if (user == null)
{
ModelState.AddModelError("Email","email or password is wrong");
return view();
}
return Redirect("/");
}
Login modal form data via ajax in ASP.NET Core 3.1
Use jQuery to send ajax and perform modal actions dynamically.
Here are codes of controller.
[HttpPost]
public IActionResult Login(LoginViewModel login)
{
if (ModelState.IsValid)
{
//var user = _userServies.getUserByEmailandPass(login.Email, login.Password);
//if (user == null)
if (login.Email.Equals(login.Password))
{
ModelState.AddModelError("Email", "email or password is wrong");
}
}else
ModelState.AddModelError("Email", "email or password invalid");
return PartialView("_LoginModalPartial", login);
}
Here are codes of _LoginModalPartial.cshtml.
#model LoginViewModel
#{
Layout = "_Layout";
}
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#login">
Login
</button>
<div id="modal-placeholder">
<!-- Modal -->
<div class="modal fade" id="login" tabindex="-1" role="dialog" aria-labelledby="addContactLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addContactLabel">Login</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form asp-action="Login">
<input name="IsValid" type="hidden" value="#ViewData.ModelState.IsValid.ToString()" />
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-save="modal">Login</button>
</div>
</div>
</div>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
<script>
$(function () {
$('button[data-save="modal"]').click(function (event) {
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
var placeholderElement = $('#modal-placeholder');
var newBody = $('.modal-body', data);
// find IsValid input field and check it's value
// if it's valid then hide modal window
var isValid = newBody.find('[name="IsValid"]').val() == 'True';
if (isValid) {
placeholderElement.find('.modal').modal('hide');
location.href = "/";
} else {
placeholderElement.find('.modal-body').replaceWith(newBody);
}
});
});
});
</script>
You should use javascript (do a post request) to send the form to the Login post action. On the success of the ajax call you need to replace the content of your modal with the partialview (=data) that your action will return
$.ajax({
type: 'POST',
url: url to your action,
data: new FormData($("#modal_form")[0]),
success: function (data) {
$("#site_modal").html(data);
}
});
In the login method change the return View(); with return PartialView();. The partialview will only return the html of the action (=excluding the layout page that will be added when using View())
Related
Technology Info:
Framework = Asp.Net Core 3.1
IDE = VisualStudio 2019
Problem:
I have a controller with Update and Delete Action Methods. I have UpdateView and DeleteView from where I need to redirect to the respective controller. I have implemented a button that can submit the form. Still I'm facing HTTP ERROR 405 Issues with PUT & DELETE. Can somebody help me to resolve this issue. Thanks in advance
Controller:
[HttpPut]
[ActionName("ModifyEmployee")]
public IActionResult ModifyEmployee(int employeeId, Malips.Data.Employee employee)
{
if (ModelState.IsValid)
{
Malips.Data.Employee employeeDetail = _hrService.EmployeeSystem.UpdateEmployee(employee);
return View("GetEmployee", employeeDetail);
}
return View();
}
[HttpDelete]
public IActionResult DeleteEmployee(int employeeId)
{
_hrService.EmployeeSystem.DeleteEmployee(employeeId);
return View("Index");
}
UpdateView:
#model Employee
#{
ViewBag.Title = "Modify Employee";
}
<div>
<form asp-controller="Hr" asp-action="ModifyEmployee" asp-route-employeeId="#Model.EmpId">
<div class="form-group">
<div asp-validation-summary="All" class="text-danger">
</div>
</div>
#Html.HiddenFor(e => e.EmpId)
<div class="form-group row">
<label asp-for="FirstName" class="col-sm-2">First Name</label>
<input asp-for="FirstName" class="col-sm-10" />
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-info">Update</button>
</form>
</div>
DeleteView:
<form asp-controller="Hr" asp-action="DeleteEmployee" asp-route-employeeId="#Model.EmpId">
<div class="row card" style="width: 18rem;">
<div class="card-body">
<label hidden="hidden">#Model.EmpId</label>
<h5 class="card-title">#Model.FirstName #Model.LastName</h5>
<p class="card-text">#Model.Salary </p>
<button type="submit" class="btn btn-danger">Delete</button>
</div>
</div>
</form>
The current HTML5 does not support PUT or DELETE in forms. You can use it with ajax or httpclient only. Or you can try #Html.BeginForm razor page template if it is possible. #Html.BeginForm has post metod choice.
For now remove [ActionName("ModifyEmployee")], [httpput] and [httpdelete] from your action attributes.
And change
public IActionResult ModifyEmployee(int employeeId, Malips.Data.Employee employee)
to:
public IActionResult ModifyEmployee(Employee employee)
since you don't use and don't need emploeeId. And remove asp-route-employeeId="#Model.EmpId" from ModifyEmployee view too.
Like #Sergey said,You can use it with ajax.Below is a working demo.
UpdateView:
<div>
<form id="update" asp-controller="Hr" asp-action="ModifyEmployee">
<div class="form-group">
<div asp-validation-summary="All" class="text-danger">
</div>
</div>
#Html.HiddenFor(e => e.EmpId)
<div class="form-group row">
<label asp-for="FirstName" class="col-sm-2">First Name</label>
<input asp-for="FirstName" class="col-sm-10" />
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
<div class="form-group row">
<label asp-for="LastName" class="col-sm-2">First Name</label>
<input asp-for="LastName" class="col-sm-10" />
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
<button type="submit" id="submit" class="btn btn-info">Update</button>
</form>
</div>
#section scripts
{
<script>
$("#submit").click(function (e) {
e.preventDefault();
var data = $('#update').serialize();
$.ajax({
type: "PUT",
url: "/hr/Modifyemployee",
data: data,
success: function (response) {
window.location.href = response.redirectToUrl;
}
});
})
</script>
}
ModifyEmployee Action
[HttpPut]
[ActionName("ModifyEmployee")]
//remember add this.
[ValidateAntiForgeryToken]
public async Task<IActionResult> ModifyEmployee(Employee employee)
{
//....
return new JsonResult(new { redirectToUrl = Url.Action("Index", "Hr") });
}
DeleteView:
<div>
<form id="delete" asp-controller="Hr" asp-action="DeleteEmployee" asp-route-employeeId="#Model.EmpId">
<div class="row card" style="width: 18rem;">
<div class="card-body">
<label hidden="hidden">#Model.EmpId</label>
<h5 class="card-title">#Model.FirstName #Model.LastName</h5>
<button type="submit" id="submit" class="btn btn-danger">Delete</button>
</div>
</div>
</form>
</div>
#section scripts
{
$("#submit").click(function (e) {
e.preventDefault();
$.ajax({
type: "delete",
url: "/hr/DeleteEmployee?id=" + #Model.EmpId,
success: function (response) {
window.location.href = response.redirectToUrl;
}
});
})
</script>
}
DeleteEmployee Action
[HttpDelete]
public async Task<IActionResult> DeleteEmployee(int id)
{
//......
return new JsonResult(new { redirectToUrl = Url.Action("Index", "hr") });
}
Test Result:
Say, on a page I have a list of items and a Delete button next to each. Upon clicking, I want to show a pop-up with a confirmation message.
The confirmation dialog and the deletion functionality are put into a view component.
I know I can do like this:
foreach (var item in Model.List)
{
<tr class="row">
<td class="col-12">
#item.Name
<button class="btn btn-danger ml-auto" data-toggle="modal"
data-target="#delete-item-#item.Id">×</button>
<vc:delete-item-dialog id="delete-item-#item.Id" item-id="#item.Id"></vc:delete-item-dialog>
</td>
</tr>
}
But then each delete-item-dialog view component is rendered separately, bloating the size of the generated HTML.
Is it possible to place that view component only in one place, after the end of the list, and provide the item-id parameter more dynamically?
Is it possible to place that view component only in one place, after the end of the list, and provide the item-id parameter more dynamically?
Yeah, you can use ajax to load the view component dynamically. Below is a working demo.
View:
#model List<User>
<table>
#foreach (var item in Model)
{
<tr class="row">
<td class="col-12">
#item.Name
<button class="btn btn-danger ml-auto" onclick="deleteuser(#item.Id)">
×
</button>
</td>
</tr>
}
</table>
<div id="container">
</div>
#section scripts{
<script>
function deleteuser(id){
$.ajax({
type: 'get',
url: 'GetMyViewComponent?id=' + id,
success: function (result) {
$("#container").html(result);
$('.modal').modal('show');
}
})
}
</script>
}
Controller:
public IActionResult UserList()
{
var users = new List<User>
{
new User{ Id = 1, Name = "Mike"},
new User{ Id = 2, Name = "John"},
new User{ Id = 3, Name = "David"},
};
return View(users);
}
public IActionResult GetMyViewComponent(int id)
{
return ViewComponent("PopUp", id);
}
PopUpViewComponent class:
public class PopUpViewComponent : ViewComponent
{
public IViewComponentResult Invoke(int id)
{
return View(id);
}
}
PopUpViewComponent Razor View:
#model int
<div class="modal fade" id="delete-#Model" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure to delete #Model?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary">Ok</button>
</div>
</div>
</div>
</div>
Result:
I have a problem with passing data from view to controller... When I was clicked button which sending POST - I have got only data for Category.Name. No subcategories, no ids etc. I am thinking I do something wrong with my view but i am not sure...
I need really help. Thanks for everything comments.
That is my View:
#model AplikacjaFryzjer_v2.Models.Category
#{
ViewData["Title"] = "Edytuj kategorię";
Layout = "~/Views/Shared/_Layout.cshtml";
var SubcategoriesData = (IList<AplikacjaFryzjer_v2.Models.Subcategory>)ViewBag.Subcategories;
}
<h1>Edytuj kategorię</h1>
<form method="post">
<div class="form-group row">
<div class="col">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="col-sm-10 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Name" disabled class="form-control" />
</div>
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<button class="btn btn-primary" type="submit" id="update">Aktualizuj kategorię</button>
</div>
<div class="col">
#if (SubcategoriesData != null)
{
<div class="col-sm-10 col-form-label">
<div id="subcatContainer">
#foreach (var subcategory in SubcategoriesData.ToList())
{
<div class="form-group col-sm-6">
<input asp-for="#subcategory.Name" />
<button class="btn btn-danger" type="button" id="remove">Usuń</button>
<span asp-validation-for="#subcategory.Name" class="text-danger"></span>
</div>
}
</div>
<button type="button" class="btn btn-secondary" id="add">Dodaj podkategorię</button>
</div>
}
else
{
<div id="container" class="col-md-6">
<label id="labelName">Nazwa podkategorii</label>
<input id="inputName" />
<button type="button" class="btn btn-secondary" id="addNew">Dodaj</button>
</div>
}
</div>
</div>
</form>
<script>
$(document).ready(function (e) {
// Variables
var i = #SubcategoriesData.Count()-1;
// Add rows to the form
$("#add").click(function (e) {
var html = '<p /><div class="form-group col-sm-6"><input asp-for="Subcategories[' + i + '].Name" /><button class="btn btn-danger" type="button" id="remove">Usuń</button></div>';
i++;
$("#subcatContainer").append(html).before();
});
// Remove rows from the form
$("#subcatContainer").on('click', '#remove', function (e) {
i--;
$(this).parent('div').remove();
});
// Populate values from the first row
});
</script>
My Actions EditCategory in controller:
[HttpGet]
public ViewResult EditCategory(int Id)
{
var category = _categoriesRepository.GetCategory(Id);
if (category == null)
{
ViewBag.ErrorMessage = $"Kategoria o id = {Id} nie została odnaleziona";
return View("NotFound");
}
ViewBag.Subcategories = category.Subcategories;
return View(category);
}
[HttpPost]
public IActionResult EditCategory(Category category)
{
if (!ModelState.IsValid)
{
// store Subcategories data which has been added
ViewBag.Subcategories = category.Subcategories == null ? new List<Subcategory>() { } : category.Subcategories;
return View("EditCategory");
}
_categoriesRepository.UpdateCategory(category);
return RedirectToAction("ManageCategories");
}
And my object (model):
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public List<Subcategory> Subcategories {get;set;}
}
I have got only data for Category.Name. No subcategories, no ids etc.
Based on your Category model class, the property Subcategories is defined as List<Subcategory>, to make form data values that browser user post could be automatically bound to this property, you can modify the field of Subcategories related to <input asp-for="#Subcategories[i].Name" /> as below.
#model AplikacjaFryzjer_v2.Models.Category
#{
ViewData["Title"] = "Edytuj kategorię";
Layout = "~/Views/Shared/_Layout.cshtml";
var Subcategories = (IList<AplikacjaFryzjer_v2.Models.Subcategory>)ViewBag.Subcategories;
}
<form method="post">
<div class="form-group row">
#*code for other fields*#
<div class="col">
#if (Subcategories != null)
{
<div class="col-sm-10 col-form-label">
<div id="subcatContainer">
#for (int i = 0; i < Subcategories.Count; i++)
{
<div class="form-group col-sm-6">
<input asp-for="#Subcategories[i].Name" />
<button class="btn btn-danger" type="button" id="remove">Usuń</button>
<span asp-validation-for="#Subcategories[i].Name" class="text-danger"></span>
</div>
}
</div>
<button type="button" class="btn btn-secondary" id="add">Dodaj podkategorię</button>
</div>
}
else
{
<div id="container" class="col-md-6">
<label id="labelName">Nazwa podkategorii</label>
<input id="inputName" />
<button type="button" class="btn btn-secondary" id="addNew">Dodaj</button>
</div>
}
</div>
</div>
</form>
Update:
why new inputs added by jquery not sending to my controller? I have got "" in my code jquery
As I mentioned in comment, please not use tag helper syntax on js client. You can try to manually set name and value attribute for new generated input field(s)
like below.
$(document).ready(function (e) {
// Variables
var i = #Subcategories.Count();
// Add rows to the form
$("#add").click(function (e) {
//var html = '<p /><div class="form-group col-sm-6"><input asp-for="Subcategories[' + i + '].Name" /><button class="btn btn-danger" type="button" id="remove">Usuń</button></div>';
var html = '<p /><div class="form-group col-sm-6"><input name="Subcategories[' + i + '].Name" value="" /><button class="btn btn-danger" type="button" id="remove">Usuń</button></div>';
i++;
$("#subcatContainer").append(html).before();
});
// Remove rows from the form
$("#subcatContainer").on('click', '#remove', function (e) {
i--;
$(this).parent('div').remove();
});
// Populate values from the first row
});
Test Result
I'm trying to find out the best way to create a submit and add button action in a controller.
I have a HttpGet for Create (Submit) but not sure how to do a HttpPost or if Get or Post is even needed:
[HttpGet]
public IActionResult Create()
{
var drafList = _drService.GetDraft().ToList();
var IndexViewModel = new IndexViewModel();
IndexViewModel.Draft = draftList;
IndexViewModel.Published = _drService.GetPublished();
IndexViewModel.Current = _drService.GetCurrent();
return View(IndexViewModel);
}
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text- danger"></div>
<div class="form-group">
<div class="col-md-3">
<label for="asof">As of:</label>
</div>
<div class="col-md-9">
<input name="AsOf" type="date" title="AsOf" class="form-control" />
</div>
</div>
<div class="clearfix col-md-12"></div>
<div class="clearfix col-md-12"></div>
<div class="form-group">
<div class="col-md-2">
<label for="title">Title:</label>
</div>
<div class="col-md-9 col-md-offset-1">
<input type="text" class="form-control" id="title" />
</div>
<div class="col-md-6">
<input type="submit" value="Add" class="btn btn-primary" />
</div>
</div>
</form>
</div>
</div>
I expect when clicking the Add button to perform the actions in the controller and add the record.
I think you can make a controller action with the same name (create() in this case) but with the [httpPost] prefix on the action so that the form would call the post create action when submitted
GET is for non-destructive actions, i.e. the same GET request should return the same response when repeated. For a create, you need to use a POST. Basically, you need to add an action like:
[HttpPost]
public async Task<IActionResult> Create(IndexViewModel model)
{
if (!ModelState.IsValid)
return View(model);
// map the data posted (`model`) onto your entity class
var entity = new MyEntity
{
Foo = model.Foo,
Bar = model.Bar
};
_context.Add(entity);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
My modal box is inside of a vue component. When the data is submitted, I want the component to send back the response data to the parent so I can append it to the root element.
The component
<template>
<div v-if="value.startsWith('new')">
<!-- Create Client Modal -->
<div class="modal show" id="modal-create-client" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button " class="close" data-dismiss="modal" aria-hidden="true" #click.prevent="close">×</button>
<h4 class="modal-title">Details</h4>
</div>
<div class="modal-body">
<!-- Form Errors -->
<div class="alert alert-danger" v-if="createForm.errors.length > 0">
<p><strong>Whoops!</strong> Something went wrong!</p>
<br>
<ul>
<li v-for="error in createForm.errors">
{{ error }}
</li>
</ul>
</div>
<!-- Create Client Form -->
<form class="form-horizontal" role="form">
<!-- Name -->
<div class="form-group">
<label class="col-md-3 control-label">First Name</label>
<div class="col-md-7">
<input id="create-client-name" type="text" class="form-control" #keyup.enter="store" v-model="createForm.first">
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">Last Name</label>
<div class="col-md-7">
<input type="text" class="form-control" name="last" #keyup.enter="store" v-model="createForm.last">
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">Email</label>
<div class="col-md-7">
<input type="text" class="form-control" name="organization" #keyup.enter="store" v-model="createForm.email">
<span class="help-block">Email is required for invoices</span>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">Organization</label>
<div class="col-md-7">
<input type="text" class="form-control" name="organization" #keyup.enter="store" v-model="createForm.organization">
</div>
</div>
</form>
</div>
<!-- Modal Actions -->
<div class="modal-footer" v-if="value == 'newClient'">
<button type="button" class="btn btn-default" data-dismiss="modal" #click.prevent="close">Close</button>
<button type="button" class="btn btn-primary" #click="storeClient">Create</button>
</div>
<div class="modal-footer" v-else-if="value == 'newLead'">
<button type="button" class="btn btn-default" data-dismiss="modal" #click.prevent="close">Close</button>
<button type="button" class="btn btn-primary" #click="storeLead">Create</button>
</div>
<div class="modal-footer" v-else-if="value == 'newContact'">
<button type="button" class="btn btn-default" data-dismiss="modal" #click.prevent="close">Close</button>
<button type="button" class="btn btn-primary" #click="storeContact">Create</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
createForm: {
errors: [],
first: '',
last: '',
email: '',
organization: ''
},
};
},
props: ['value'],
/**
* Prepare the component (Vue 1.x).
*/
ready() {
this.prepareComponent();
},
/**
* Prepare the component (Vue 2.x).
*/
mounted() {
var vm = this
this.prepareComponent();
},
methods: {
/**
* Prepare the component.
*/
prepareComponent() {
$('#modal-create-client').on('shown.bs.modal', () => {
$('#create-client-name').focus();
});
$("#modal-create-client").on("hide.bs.modal", function(e) {
$(this).removeData('bs.modal');
});
},
close() {
$('#modal-create-client').removeClass('show');
},
/**
* Create a new client for the user.
**/
storeClient() {
this.persistClient(
'post', './clients/add',
this.createForm, '#modal-create-client'
);
},
storeLead() {
this.persistClient(
'post', './leads/add',
this.createForm, '#modal-create-client'
);
},
storeContact() {
this.persistClient(
'post', './contacts/add',
this.createForm, '#modal-create-client'
);
},
/**
* Persist the client to storage using the given form.
*/
persistClient(method, uri, form, modal) {
form.errors = [];
this.$http[method](uri, form).then(response => {
location.reload();
$(modal).modal('hide');
}).catch(response => {
if (typeof response.data === 'object') {
form.errors = _.flatten(_.toArray(response.data));
} else {
form.errors = ['Something went wrong. Please try again.'];
}
});
},
watch: {
value: function (value) {
// update value
$(this.$el).val(value)
},
}
}
}
</script>
The root Element
var MyComponent = Vue.component('my-ajax-component',
require('./components/Toolbar.vue') );
new Vue({
el: '#select',
data: {
selected: ''
},
components: {
// <my-component> will only be available in parent's template
'my-ajax-component': MyComponent
}
});
and my view
<div class="form-group clearfix">
<div class="col-xs-12" id="select">
{!! Form::label('client_id', 'Choose Client:', ['class' => 'control-label']) !!}
{!! Form::select('client_id', ['newClient' => 'New Client', $clients], null, ['title' => 'Select Client', 'class' => 'form-control selectpicker', 'v-model' => 'selected', 'data-live-search' => 'true']) !!}
<br>
<my-ajax-component v-bind:value="selected"></my-ajax-component>
</div>
</div>
Instead of location reload I want to append the response data to the select element which is my roo
I changed my root element to
new Vue({
el: '#select',
data: {
selected: '',
data: ''
},
components: {
// <my-component> will only be available in parent's template
'my-ajax-component': MyComponent
},
methods: {
handler: function(data) {
console.log('this is my data' + data)
}
}
my component now has
this.$emit('data-received',response)
and put v-on in the child component
<my-ajax-component v-bind:value="selected" v-on:data-received='handler(data)'></my-ajax-component>
I get data undefined or nothing
I can see the data returned in the post .. it's the id of my object ...should I json encode it
The easiest way can be to emit the event with data in child component when you get the response.
In child:
this.$emit('data-received',response)
In parrent:
<child-component v-on:data-received='handler(data)'>
In handler function in parrent, do whatever you want with data.
UPDATED:
Your backend should return JSON to follow REST Api standards.
Every endpoint of API should return JSON, even if it is simple string.
Instead of
In parrent:
<child-component v-on:data-received='handler(data)'>
I used In parrent:
<child-component v-on:data-received='handler'>