Passing data to an array in Vue.js - javascript

I'm sure it's something simple, but I can't get this to work. I've read the documentation and other sources, but I am just not understanding. I simply want to pass data that I retrieve with ajax to an empty array. I've ensured that the data is indeed successfully coming from the server, but it does not appear to get assigned to UserArticles, and does not update the DOM. What am I missing. Here's my code:
Component:
Vue.component('article-selection', {
props: ['articles'],
template: '<div> <p>{{articles.title}}</p> </div>'
})
Vue:
var Article = {};
var UserArticles = [];
var vm = new Vue({
el: '#createNewArticle',
data: {
Article: Article,
UserArticles: UserArticles
},
computed: {
isNewArticle: function () {
return this.Article.ArticleIdentification.Id.length < 5
}
},
created: function(){
this.getUserArticles();
},
methods: {
setUserId: function (id) {
//code
},
createNewArticle: function (msg) {
//code},
getUserArticles: function () {
$.ajax({
method: "GET",
url: "/api/Article/GetUserArticles"
}).done(function (rData, status, jq) {
UserArticles = rData;
toastr.success('', 'Retrieved User Articles');
}).fail(function (rData, status, error) {
var result = $.parseJSON(rData.responseText);
toastr.warning(result.messages, 'Retrieve User Articles')
});
}
}
})
HTML:
<div class="row" id="createNewArticle" >
<div class="col-sm-12">
<!--Create Initial article-->
<div class="row" v-if="true">
<div class="col-sm-12 text-center">
<div>Passed: {{Article.UserId}}</div>
<div class="form" style="display: inline-block;" id="newArticleForm">
<div class="form-group">
<label for="ArticleName">Article Title</label>
<input type="text" class="form-control" id="ArticleTitle"
name="ArticleTitle" v-model="Article.ArticleIdentification.Title" /><br />
<p>{{Article.ArticleIdentification.Title}}</p>
<button class="btn btn-sm" v-on:click="createNewArticle('hey hey')">
Create New Article
</button>
</div>
</div>
</div>
<div class="col-sm-12">
<!--COMPONENT HERE--!>
<article-selection v-for="(artId, index) in UserArticles"
v-bind:key="artId.id"
v-bind:index="index"
v-bind:articles="artId"></article-selection>
</div>
</div>
</div>

Try writing the method like this
$.ajax({
method: "GET",
url: "/api/Article/GetUserArticles"
success: function (data) {
UserArticles = data;
},
error: function (error) {
alert(JSON.stringify(error));
}
})
}

I had to use an arrow function in my ajax code inside of the done function as well as add the this keyword. Note the difference:
getUserArticles: function () {
$.ajax({
method: "GET",
url: "/api/Article/GetUserArticles"
}).done((rData, status, jq) => {
this.UserArticles = rData;
toastr.success('', 'Retrieved User Articles');
}).fail(function (rData, status, error) {
var result = $.parseJSON(rData.responseText);
toastr.warning(result.messages, 'Retrieve User Articles')
});
}

Related

How can I serialize a form in JavaScript asp.net

I am using some javascript to post my form but I dont want to have to submit each form field is there a way I can serlize this to an object in .net so that it will bring in all the form contents.
section Scripts {
<script>
function confirmEdit() {
swal({
title: "MIS",
text: "Case Created your Case Number is " + $("#Id").val(),
icon: "warning",
buttons: true,
dangerMode: true,
}).then((willUpdate) => {
if (willUpdate) {
$.ajax({
url: "/tests/edit/" + $("#Id").val(),
type: "POST",
data: {
Id: $("#Id").val(),
Name: $("#Name").val()
},
dataType: "html",
success: function () {
swal("Done!", "It was succesfully edited!", "success")
.then((success) => {
window.location.href = "/tests/index"
});
},
error: function (xhr, ajaxOptions, thrownError) {
swal("Error updating!", "Please try again", "error");
}
});
}
});
}
</script>
}
asp.net core will automatically bind json data using the [FromBody] attribute.
data: {
id: $("#Id").val(),
name: $("#Name").val()
},
and then in your controller
[HttpPost("/tests/edit/")]
public IActionResult Process([FromBody] MyData data){ ... }
where MyData is
public class MyData
{
public string Id {get;set;}
public string Name {get;set;}
}
section Scripts { function confirmEdit() {
swal({ title: "MIS", text: "Case Created your Case Number is " + $("#Id").val(), icon: "warning", buttons: true, dangerMode: true, }).then((willUpdate) => { if (willUpdate) {
var obj = { Id: $("#Id").val(), Name: $("#Name").val() }
$.ajax({ url: "/tests/edit/" + $("#Id").val(), type: "POST", data: JSON.Stringify(obj), dataType: "html", success: function () { swal("Done!", "It was succesfully edited!", "success") .then((success) => { window.location.href = "/tests/index" }); }, error: function (xhr, ajaxOptions, thrownError) { swal("Error updating!", "Please try again", "error"); } }); } }); } }
in c# use
public ActionResult FormPost(MyData obj)
Please refer to the following methods to submit the form data to action method:
using the serialize() method to serialize the controls within the form.
#model MVCSample.Models.OrderViewModel
<h4>OrderViewModel</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Showsummary" asp-controller="Home" method="post" class="signup-form">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="OrderId" class="control-label"></label>
<input asp-for="OrderId" class="form-control" />
<span asp-validation-for="OrderId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="OrderName" class="control-label"></label>
<input asp-for="OrderName" class="form-control" />
<span asp-validation-for="OrderName" class="text-danger"></span>
</div>
<div id="packages">
#for (int i = 0; i < Model.Packages.Count; i++)
{
<div class="form-group">
<label asp-for="#Model.Packages[i].Pid" class="control-label"></label>
<input asp-for="#Model.Packages[i].Pid" class="form-control" />
<span asp-validation-for="#Model.Packages[i].Pid" class="text-danger"></span>
<br />
<label asp-for="#Model.Packages[i].PackageTitle" class="control-label"></label>
<input asp-for="#Model.Packages[i].PackageTitle" class="form-control" />
<span asp-validation-for="#Model.Packages[i].PackageTitle" class="text-danger"></span>
</div>
}
</div>
</form>
</div>
</div>
<div>
<input type="button" id="summary" value="Summary" />
<div id="page_3">
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(function () {
$("#summary").click(function () {
console.log("calling summary");
event.preventDefault();
$.ajax({
type: "POST",
url: "/Home/Showsummary", //remember change the controller to your owns.
data: $("form.signup-form").serialize(),
success: function (data) {
console.log(data)
},
failure: function (response) {
console.log(response.responseText);
},
error: function (response) {
console.log(response.responseText);
}
});
});
});
</script>
Code the the action method:
[HttpPost]
public PartialViewResult Showsummary(OrderViewModel model)
{
try
{
//...
return PartialView("OrderSummary", model);
}
catch
{
return PartialView("OrderSummary", model);
}
}
After clicking the button, the result like this:
As we can see that, we could get the element's value in the form and even the nested entity.
Note: Only "successful controls" are serialized to the string. No submit button value is serialized since the form was not submitted using a button. For a form element's value to be included in the serialized string, the element must have a name attribute. Values from checkboxes and radio buttons (inputs of type "radio" or "checkbox") are included only if they are checked. Data from file select elements is not serialized.
Create a JavaScript object, and post it to action method.
Change the JavaScript script as below:
$(function () {
$("#summary").click(function () {
console.log("calling summary");
event.preventDefault();
//create a object to store the entered value.
var OrderViewModel = {};
//using jquery to get the entered value.
OrderViewModel.OrderId = $("input[name='OrderId']").val();
OrderViewModel.OrderName = $("input[name='OrderName']").val();
var packages = [];
//var count = $("#packages>.form-group").length; //you could use it to check the package count
$("#packages>.form-group").each(function (index, item) {
var package = {}
package.Pid = $(item).find("input[name='Packages[" + index + "].Pid']").val();
package.PackageTitle = $(item).find("input[name='Packages[" + index + "].PackageTitle']").val();
packages.push(package);
});
//add the nested entity
OrderViewModel.Packages = packages;
$.ajax({
type: "POST",
url: "/Home/Showsummary", //remember change the controller to your owns.
data: OrderViewModel,
success: function (data) {
console.log(data)
$('#page_3').html(data);
},
failure: function (response) {
console.log(response.responseText);
},
error: function (response) {
console.log(response.responseText);
}
});
});
});
By using the above code, I could also get the submit entity, you could refer to it.

How to pass data from a component to an Instance in Vue

I am trying to get data from a component and pass it to a variable in my root Vue instance.
My Vue Instance:
new Vue({
el: '#root',
data: {
searchResultObject: ''
},
methods: {
//....
}
});
My Global Component:
Vue.component('user-container-component', {
props: {
prop: null
},
template: '#user-container-template',
data: function () {
return {
searchResultObject: ''
}
},
methods: {
dbSearch_method: function () {
var self = this;
$.ajax({
url: 'Home/LocalSearch',
type: 'GET',
success: function (response) {
self.searchResultObject = response;
},
error: function () {
alert('error');
}
});
}
}
})
Pressing a button in my UI triggers the dbSearch_method, that part works. I am wondering how I get the data to the searchResultObject in my instance, not the component?
HTML:
<button class="btn btn-link bold" v-on:click="dbSearch_method">{{item}}</button></li>
EDIT:
HTML:
<div id="root">
//...
<div id="collapse2" class="panel-collapse collapse">
<ul class="list-group">
<root-component v-for="item in customerObject"
v-bind:prop="item"
v-bind:key="item.id">
</root-component>
</ul>
</div>
</div>
//...
<script type="text/x-template" id="root-template">
<li class="list-group-item">
<div class="bold">
<button v-if="open" v-on:click="toggle" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down" style="color: black"></span></button>
<button v-else="open" v-on:click="toggle" class="btn btn-link"><span class="glyphicon glyphicon-chevron-right" style="color: black"></span></button>
<button class="btn btn-link bold">{{prop.name}}</button>
</div>
<ul class="no-bullets" v-show="open">
<park-container-component v-bind:prop="prop.parks"/>
<admin-container-component v-bind:prop="prop.admins" />
<user-container-component v-on:search-results-fetched="addSearchResults($event)" v-bind:prop="prop.admins" />
</ul>
</li>
</script>
<script type="text/x-template" id="user-container-template">
<li class="list-group-item">
<div class="bold">
<button v-if="open" v-on:click="toggle" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down" style="color: black"></span></button>
<button v-else="open" v-on:click="toggle" class="btn btn-link"><span class="glyphicon glyphicon-chevron-right" style="color: black"></span></button>Users
<button class="btn btn-primary btn-xs pull-right" data-toggle="modal" data-target="#inviteAdminModal">Add</button>
</div>
<ul class="no-bullets" v-show="open" v-for="item in prop">
<li><button class="btn btn-link bold" v-on:click="dbSearch_method">{{item}}</button></li>
</ul>
</li>
</script>
Script:
new Vue({
el: '#root',
data: {
//...
searchResultObject: ''
},
methods: {
//...
addSearchResults: function(data) {
alert('adding');
this.searchResultObject = data;
}
}
});
Vue.component('user-container-component', {
props: {
prop: null
},
template: '#user-container-template',
data: function () {
return {
open: false
}
},
methods: {
toggle: function () {
this.open = !this.open;
},
dbSearch_method: function () {
var self = this;
$.ajax({
url: 'Home/LocalSearch',
type: 'GET',
success: function (response) {
self.$emit('search-results-fetched', response);
},
error: function () {
alert('error');
}
});
}
}
})
As you said the component user-container-component is inside element with id #root, assming your html to be like this:
<div id="root">
<user-container-component></user-container-component>
</div>
in your user-container-component emit an event in the succss callback of your dbSearch_method ajax request like this:
Vue.component('user-container-component', {
props: {
prop: null
},
template: '#user-container-template',
data: function () {
return {
searchResultObject: ''
}
},
methods: {
dbSearch_method: function () {
var self = this;
$.ajax({
url: 'Home/LocalSearch',
type: 'GET',
success: function (response) {
this.$emit('search-results-fetched', response);
},
error: function () {
alert('error');
}
});
}
}
})
in your html setup an event listener on the user-container-component like this:
<div id="root">
<user-container-component #search-results-fetched="addSearchResults($event)"></user-container-component>
</div>
in your root instance add addSearchResults method:
new Vue({
el: '#root',
data: {
searchResultObject: ''
},
methods: {
addSearchResults(data){
this.searchResultObject = data;
}
}
});
You can emit the value as an event for parent to listen to
$.ajax({
url: 'Home/LocalSearch',
type: 'GET',
success: function (response) {
self.searchResultObject = response;
this.$emit('onSearchResult', response)
},
error: function () {
alert('error');
}
});
then in your parent you can fetch it by setup a listener
<user-container-component v-on:onSearchResult="parentListener"/>
For a big project, you can use vuex to manage the data.
Or you can just use eventbus to solve the same level component data transmission.here
For your situation, I think it should use $emit.
dbSearch_method: function () {
var self = this;
$.ajax({
url: 'Home/LocalSearch',
type: 'GET',
success: function (response) {
self.searchResultObject = response;
this.$emit('customEvent', response);
},
error: function () {
alert('error');
}
});
}
and in your root vue instance,you can use $on to listen the event fire.here

Clear jeasyui form fields after successful submit

I'm using a jeasyui form, inside a xoops module, in which I'm trying to clear all the form fields once the data has successfully submitted.
I've already consulted this question, but it didn't solve the problem in my case.
My HTML:
<div class="easyui-panel" title="Capture Reqs" style "width:100%;
max-width:600px; padding:30px 60px;">
<form action = "captureReqs_Save.php" id ="ff" class = "easyui-form"
method ="post" data-options = "novalidate:true">
<div style="margin-bottom:20px"> Area <br>
<input id="idArea" class="easyui-combobox" style="width:260px" name="idArea"
data-options="
url:'areasJson.php?idZona=<?php echo $idZone; ?>',
label:'Area:',
valueField: 'id',
textField: 'desc',
required:true
">
</div>
<div style="margin-bottom:20px"> Material
<input id="IdMaterial" class="easyui-combobox" style="width:100%"
name="IdMaterial" data-options="
loader: myloader,
mode: 'remote',
valueField: 'code',
textField: 'desc',
required:true
">
<div style="margin-bottom:20px"> Qty
<input class="easyui-textbox" name="quantity" style="width:100%"
data-options="label:'Qty:',required:true, validType:'number'">
</div>
<div style="margin-bottom:20px">
</form>
<div style="text-align:center;padding:5px 0">
<a href="javascript:void(0)" class="easyui-linkbutton"
onClick = "submitForm()" style="width:80px"> Submit</a>
<a href="javascript:void(0)" class="easyui-linkbutton"
onClick = "resetForm()" style = "width:80px"> Clear </a>
</div>
</div>
Script:
<script>
var myloader = function (param, success, error) {
var q = param.q || '';
if (q.length <= 2) {
return false
}
$.ajax({
url: 'materialJson.php?idArea=' + $('#idArea').combobox('getValue'),
dataType: 'json',
data: {
q: q
},
success: function (data) {
var items = $.map(data, function (item, index) {
return {
code: item.code,
desc: item.desc
};
});
success(items);
},
error: function () {
error.apply(this, arguments);
}
});
}
function submitForm() {
$('#ff').form('submit', {
onSubmit: function () {
return $(this).form('enableValidation').form('validate');
}
});
}
function resetForm() {
$('#ff')[0].reset();
}
</script>
Try calling resetForm. I converted to use promise style ajax and added resetForm
var myloader = function (param, success, error) {
var q = param.q || '';
if (q.length <= 2) {
return false
}
$.ajax({
url: 'materialJson.php?idArea=' + $('#idArea').combobox('getValue'),
dataType: 'json',
data: {
q: q
}
}).then(function (data) {
var items = $.map(data, function (item, index) {
return {
code: item.code,
desc: item.desc
};
});
success(items);
}).fail(function () {
error.apply(this, arguments);
});
}
function submitForm() {
$('#ff').submit(function () {
if ($(this).form('enableValidation').form('validate')) {
$.post($(this).attr('action'), $(this).serialize(), function (response) {
clearForm();
});
}
return false;
});
}
function resetForm() {
$('#ff')[0].reset();
}

How to set the id for the new created item with Knockout

The problem is that I cannot update a new created item, because on the server I receive no Id.
I am trying to learn Knockout, and I am not able to find a way to provide the Id to new created items.
I have an object with Id, and Name, using knockout I can make all Crud operations, but, after inserting a new item, if I try to change his name I am not able because that item has no Id value.
My question is: Every time when I add a new item I need to get a fresh collection of items back to the view, and rebind the view?
or, there is a way to another way to provide the Id to the new inserted items?
Here is my code:
function Person(id, name) {
var self = this;
self.Id = ko.observable(id);
self.nume = ko.observable(name);
}
function PersonVm() {
var self = this;
self.Persons = ko.observableArray([]);
self.newPerson = ko.observable(new Person())
self.isModificare = false;
self.addPerson = function () {
if (!self.isModificare) {
$.ajax("/Person/AddPerson", {
data: ko.toJSON({ Person: self.newPerson }),
type: "post", contentType: "application/json",
success: function (result) { alert(result.mesaj); }
});
} else {
$.ajax("/Person/UpdatePerson", {
data: ko.toJSON({ Person: self.newPerson }),
type: "post", contentType: "application/json",
success: function (result) { alert(result) }
});
}
self.isModificare = false;
if (!self.isModificare) self.Persons.unshift(self.newPerson());
self.newPerson(new Person());
}
self.removePerson = function () {
$.ajax("/Person/DeletePerson", {
data: ko.toJSON({ Person: self.newPerson }),
type: "post", contentType: "application/json",
success: function (result) { alert(result) }
});
self.Persons.remove(self.newPerson());
self.newPerson(new Person());
}
self.ModificaPerson = function (person) {
self.newPerson(person);
self.isModificare = true;
}
$.getJSON("/Person/GetPersons", function (allData) {
var mapPerson = $.map(allData, function (item) { return new Person(item.Id,item.Name) });
self.Persons(mapPerson);
});
}
ko.applyBindings(new PersonVm());
Edit:
This is the view:
<div class="input-group">
<input type="text" class="form-control" data-bind="value: newPerson().name">
<span class="input-group-btn">
<button class="btn btn-default" data-bind="click:addPerson">
<span class="glyphicon glyphicon-plus-sign" style="color:green"></span>
</button>
</span>
<span class="input-group-btn">
<button class="btn btn-default" data-bind="click:$root.removePerson">
<span class="glyphicon glyphicon-trash" style="color:red"></span>
</button>
</span>
</div>
<ul data-bind="foreach: Perons" class="list-group" id="content">
<li class="list-group-item" data-bind="text: name,click:$root.ModificaPerson"></li>
</ul>
Two steps to get what you want:
Ensure that your "Person/AddPerson" Web service return the ID of the created object.
Change your update method so that it sets an ID on the newPerson property:
$.ajax("/Person/AddPerson", {
data: ko.toJSON({ Person: self.newPerson }),
type: "post", contentType: "application/json",
success: function (result) {
self.newPerson().Id(result.Id);
}
});
Note that the above code supposes that your services returns a JSON object with an ID property named 'Id'.

Posting data to MVC Controller using AngularJS

I have a simple html form with 2 textboxes and a button as following:
<div class="container" ng-controller="GetStudentController">
<div class="form-group" style="padding-bottom:40px;">
<h2 style="text-align:center;">Index</h2>
<input id="Text1" class="form-group form-control" ng-model="ime" type="text" />
<input id="Text1" class="form-group form-control" ng-model="prezime" type="text" />
<input type="button" style="float:right;" class="form-group btn btn-primary" ng-click="snimi(ime,prezime)" value="Snimi" />
</div>
</div>
And this is my AngularJS code:
var app = angular.module("myApp", []);
app.service("GetStudentsService", function ($http) {
this.getData = function ()
{
return $http({
metod: "GET",
url: "/Home/GetStudent"
}).success(function (data) {
return data;
}).error(function () {
alert("error");
return null;
});
}
this.PostData = function (data)
{
$http.post("/Home/SnimiStudenta",data)
.success(function () {
getData();
}).error(function (response) {
alert(response);
});
}
});
app.controller("GetStudentController", function ($scope, GetStudentsService) {
$scope.data = null;
GetStudentsService.getData().then(function (response) {
$scope.data = response.data;
});
$scope.snimi = function (ime, prezime) {
var data = $.param({
fName: ime,
lName: prezime
});
GetStudentsService.PostData(data);
};
});
And this is the action responsible for saving the record to the DB:
[HttpPost]
public void SnimiStudenta(// I would like to pass an Student object here)
{
Student s = new Student();
s.Ime = "1";
s.Prezime = "2";
Connection.dc.Students.Add(s);
Connection.dc.SaveChanges();
}
I have a few questions:
How can I mark my values from my textboxes and pass them as an Student object into my action
How can I bind the table upon saving the new record into the DB. As you can see I'm calling the function getData(); but it says its undefined...
Can someone help me out with this please?
Thanks!
You have to build a js object which looks similar to your C# class (In terms of the property name) which you use as the parameter for your action method, and post the js object
$scope.snimi = function (ime, prezime) {
var data = { Ime: ime, Prezime: prezime};
GetStudentsService.PostData(data);
};
And your action method,
[HttpPost]
public void SnimiStudenta(Student s)
{
Connection.dc.Students.Add(s);
Connection.dc.SaveChanges();
}
As far as why you get an "undefined" error when you call getData(), it is not because getData is undefined, but because getData returns a promise containing just the data, not the whole response. So change:
GetStudentsService.getData().then(function (response) {
$scope.data = response.data;
});
to:
GetStudentsService.getData().then(function (data) {
$scope.data = data;
});

Categories