I have 5 tabs with the same user's data. Each tab has an input to search by term. How can reuse code for fetching users and searching them in opened tab. Code is in this JSFiddle:
var listing = Vue.extend({
data: function () {
return {
query: '',
list: [],
user: '',
}
},
computed: {
computedList: function () {
var vm = this;
return this.list.filter(function (item) {
return item.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
})
}
},
created: function () {
this.loadItems();
},
methods: {
loadItems: function () {
this.list = ['mike','bill','tony'],
},
}
});
var list1 = new listing({
template: '#users-template'
});
var list2 = new listing({
template: '#users-template2'
});
Vue.component('list1', list1);
Vue.component('list2', list2)
var app = new Vue({
el: ".lists-wrappers",
});
query - string of term to search
ComputedList - array of filtered data by search term.
But getting error for "query" and "ComputedList".
[Vue warn]: Property or method "query" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in root instance).
You were really close with what you had. The reason for the query error is you were using query in what looked like, to Vue, the root instances scope. You shouldn't put templates inside of other templates. Always have them outside of it (preferably as a string in your component definition).
You can read about that a bit here: https://vuejs.org/guide/components.html#DOM-Template-Parsing-Caveats
Here's how I'd approach your situation: https://jsfiddle.net/crswll/apokjqxx/6/
I am quite new to AngularJs and I am building a little app with it to challenge myself.
This is very simple at first sight : I would like to be able to choose multiple criteria then choose a value, based on the chosen criterion, so we can later filter the data.
Thus, I would like to maintain a "criterion-value" couples array to send it later to the server.
All I have done so far is in this : plunker
The bug is that all "select" directives are depending to one another...
I know the problem comes from the scope of the model variables "chosenValue" and "chosenCriterion" which are shared by all directives but how to make them locale to one div that belongs to the class "_new_criterion" and at the same time accessing to the array allChoices ?
Also how should I populate my "allChoices" object to have something like
[
{
criterion : "CITY",
value : "San Francisco"
},
{
criterion : "COMPANY",
value : "Something"
}
]
I have no idea whether this is the proper way to achieve this, so feel free to suggest an other solution.
here is a sample of the app's source code:
var app = angular.module('app', []);
angular.module('app').controller('MainCtrl', function($scope, $compile) {
$scope.allCouples = [];
$scope.add = function(ev, attrs) { //$on('insertItem',function(ev,attrs){
var criterionSelector = angular.element(document.createElement('criteriondirective'));
var el = $compile(criterionSelector)($scope)
angular.element(document.body).append(criterionSelector);
};
});
app.directive('criteriondirective', function($compile) {
return {
template: '<div class="_new_criterion"><select ng-model="chosenCriterion" ng-change="chooseCriterion(chosenCriterion)" ng-options="criterion.columnName for criterion in criteria" class="form-control"></select></div>',
restrict: 'E',
replace: true,
transclude: false,
compile: function(tElement, tAttrs, transclude) {
return function(scope, element, attr) {
scope.chooseCriterion = function(sel) {
var valueSelector = angular.element(document.createElement('valuedirective'));
var el = $compile(valueSelector)(scope);
tElement.append(valueSelector);
};
//rest call to get these data
scope.criteria = [{
columnName: 'turnover',
type: 'range'
}, {
columnName: 'city',
type: 'norange'
}, {
columnName: 'company',
type: 'norange'
}];
};
}
};
});
app.directive('valuedirective', function() {
return {
template: '<select ng-model="chosenValue" ng-options="value for value in values" ng-change="chooseValue(chosenValue)" class="form-control"></select>',
restrict: 'E',
replace: true,
transclude: false,
compile: function(tElement, tAttrs, transclude) {
return function(scope, element, attr) {
scope.chooseValue = function(sel) {
//I would like to register the couple "criterion-value" into the array allCouples how to pass the criterion as parameter to this directive ?
// scope.allCouples.push({criterion : "criterion", value : "value"});
};
//Rest call to get these data
scope.values = ["Paris", "San Francisco", "Hong-Kong"];
};
}
};
});
Thank you very much
p.s.: don't pay to much attention to the values array, in real case data are fetched Restfully
Your might want to isolate the scopes of your directives, at the moment they share and change same data. Try it with scope: true, for example.
Using Extjs 3.4
My web service respond with a json string: {"msg":"Some"}
I want to populate a grid with Some .
Ext.onReady(function(){
var store = new Ext.data.JsonStore({
url: "my/json/url.json",
fields: [{name:"msg"}]
});
function StoreLoadCallback(records, operation, success){
if (success) {
console.log(records); // record is undefined
alert(records); // show 'undefined'
} else {
console.log('error');
}
}
function ajaxSearch_function(){
var query = Ext.getCmp('search').getValue();
store.load({
params: {query: query},
callback: StoreLoadCallback
});
}
var form = new Ext.FormPanel({
defaultType: 'textfield',
items: [{
fieldLabel: 'search',
name: 'search',
id: 'search'
}],
buttons: [{
text: 'Search', handler: ajaxSearch_function
}]
});
form.render('ajax-search_form');
var grid = new Ext.grid.GridPanel({
store: store,
columns: [{
id :'title',
header : 'title',
sortable : true,
dataIndex: 'title'
}],
});
grid.render('ajax-grid');
});
The web service respond well, I have tested with Curl.
The problem is populate the grid with the json response.
If you say that records variable in callback method is undefined, there is probably a problem with parsing the response. I guess it expects array instead of one single record. Try to change the contents of the json file from {"msg" : "Some"} to [{"msg" : "Some"}]
After you cross this hurdle (i. e. the response is correctly parsed), I see that your datagrid column refer to "title" rather than "msg". Title is not a member of the store, so the columns will show empty value anyway.
Also, it is not common to start method name with capital letters (except they represent "classes"), so it is kind of nicer to call the method storeLoadCallback instead of StoreLoadCallback.
I have same problem as Daniel had in this topic, but his solution doesn't work for me:
http://www.kendoui.com/forums/ui/grid/kendo-ui-grid-inserts-updates-create-duplicate-records.aspx#-jhxqRrNAUGsTFJaC-Ojwg
So use-case. Users adds 2 new records one after another:
Presses "Add new record" button of a grid
Fills the fields (name="Alex", amount=10, comment="first").
Record one is ready. Press 'Save'. (data goes to controller and than to Database)
User see one record in a grid
Press "Add new record" button again
Fills fields (name="Bob", amount=20, comment = "second").
Record one is ready. Press 'Save'. Data goes to controller and than to Database.
In this moment something happens and grid send Ajax request again with record one data to controller.
User updates grid and see three records
"Alex | 10 | first" (duplicated record) ID = 1
"Bob | 20 | second" ID = 2
"Alex | 10 | first" ID = 1
They recommend to return an ID for correct binding\update of data source with new record.
And I return it (new ID from database comes in response with bouns entity)! and this doesn't help.
Only if I add first record and refresh page with F5 and after that add second record everything is ok. But if add another one, the third records - problems appears again
Code in controller:
[HttpPost]
public JsonResult Create(BonusDto bonusDto)
{
BonusAggregate bonus;
if (bonusDto.Amount <= 0)
throw new ArgumentOutOfRangeException("Amount should be more than 0");
if (bonusDto.EmployeeId <= 0)
throw new ArgumentNullException("You should specify an existing employee");
using (var dbContext = new DatabaseContext())
{
BonusesRepository = new BonusesRepository(dbContext);
var employeeRepository = new EmployeesRepository(dbContext);
bonus = new BonusFactory(employeeRepository).Create(bonusDto);
BonusesRepository.Save(bonus);
}
HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;
return Json(bonus); // try to return ID after bonus was saved
}
UI Code
// creates bonuses grid control
$("#bonusesGrid").kendoGrid({
dataSource: bonusesDataSource,
toolbar: ["create"],
editable: "inline",
columns: [
"BonusId",
"EmployeeId",
{
field: "EmployeeLastName",
editor: employeeAutocompletingEditor,
template: "#=EmployeeLastName#"
},
"Amount",
{
field: "Comment",
titel: "Comment",
editor: textareaEditor,
filterable: {
operators: {
number: {
contains: "Contains"
}
}
}
},
{
command: ["edit"],
title: " "
}
],
save: function(e) {
if (newValueEmployeeId !== undefined &&
newValueEmployeeLastName !== undefined &&
newValueEmployeeLastName !== "") {
setNewValueEmployeeIdAndLastName(newValueEmployeeId, newValueEmployeeLastName);
gridDataSource.model.EmployeeId = newValueEmployeeId; // it's a hack to bind model and autocomplete control
gridDataSource.model.EmployeeLastName = newValueEmployeeLastName;
} else {
gridDataSource.model.EmployeeId = currentValueEmployeeId;
gridDataSource.model.EmployeeLastName = currentValueEmployeeLastName;
}
},
edit: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
},
cancel: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
}
});
Bonus data source:
// bind json result from /Bonuses/GetPagedJsonBonuses
var bonusesDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "#Url.Action("GetPagedJsonBonuses", "Bonuses")",
type : "GET",
contentType: "application/json",
dataType: "json",
cache: false
},
create: {
url: "#Url.Action("Create", "Bonuses")",
dataType: "json",
type: "POST"
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
// correct format for conversion
var d = new Date(options.Date);
options.Date = kendo.toString(d, dateFormat);
// updates the BonusDTO.EmployeeId with selected value
if (newValueEmployeeId !== undefined)
options.EmployeeId = newValueEmployeeId;
}
if(operation === "read") {
options.filter = setFormattedFilterDate(options.filter);
}
return options;
}
},
pageSize: 15,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
error: showErrorMessage,
schema: {
data: "Data", // PagedResponse.Data
total: "TotalCount", // PagedResponse.TotalCount
model: {
id: "BonusId", // Data
fields: {
EmployeeId: { type: "number" },
EmployeeLastName: {
type: "string",
editable: true,
nulable: false,
validation: { required: {message: "Employee's last name is required"}}
},
Date: {
type: "date",
editable: true,
nullable: false,
validation: {
required: { message: "Date is required to be set" }
}
},
Amount: {
type: "number",
editable: true,
nullable: false,
defaultValue: 1,
validation: {
required: { message: "Amount is required to be set" }
}
},
Comment: { type: "string", editable: true }
} // fields
} // model
}// schema
});
I haven't seen this problem in my code. I do however have a "complete" event handler on my create and update events that refreshed the grid - it may help you:
dataSource: {
type: "jsonp",
transport: {
read: UrlBase + "getAll",
update: {
url: UrlBase + "Update",
dataType: "jsonp",
complete: function (e) {
$("#grid").data("kendoGrid").dataSource.read();
}
},
create: {
url: UrlBase + "create",
dataType: "jsonp",
complete: function (e) {
$("#grid").data("kendoGrid").dataSource.read();
}
},
destroy: {
url: UrlBase + "destroy",
dataType: "jsonp",
complete: function (e) {
$("#grid").data("kendoGrid").dataSource.read();
}
}
},
...
Yes, hamed is correct. Your "create" action result passes in the object from your model that is to be saved to your database. Have the INSERT in your data access layer return the newly created key ("ID") in the database. Use this key to now set the "ID" field on your model that's passed in to the action result and then passed back to the view as JSON. Now the grid should know it's just created this record and does not need to do anything more with it. Otherwise, the model object returns with the "ID" field set to 0 so the grid thinks it still needs to add this record.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Grid_Create([DataSourceRequest] DataSourceRequest request, MyObject obj)
{
if (obj != null && ModelState.IsValid)
{
obj.Id = _myService.Create(obj);
}
return Json(new[] { obj }.ToDataSourceResult(request, ModelState));
}
This error occur when you did not pass Primary key to view in read action.
Regards
An alternative to Quinton Bernhardt's complete event: bind the dataSource.read() to the kendo sync event.
I'm using kendo's C# MVC's html helpers which don't expose the sync event, so I had to modify it after setting up the grid.
On window load:
var grid = $("#GridName").data("kendoGrid");
grid.dataSource.bind("sync", function () {
$("#GridName").data("kendoGrid").dataSource.read();
});
The sync event fires after the save request has been completed. The dataSource.read() gets the latest from the server, including the id that was set server side.
I had a similar issue, did various trials but fixed with the following trial
Jquery
create: {
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
url: "../../ajax/ajaxGv.aspx/addstaff"
},
parameterMap: function (options, operation) {
if (operation == "create" && options.models) {
return JSON.stringify({ "oStaff": options.models });
}
VB.Net
'Adding Staff
<System.Web.Services.WebMethod()> _
Public Shared Sub addStaff(ByVal oStaff As Object)
Dim strJson As String = JsonConvert.SerializeObject(oStaff)
Dim lstStaff As List(Of Staff) = JsonConvert.DeserializeObject(Of List(Of Staff))(strJson)
Dim db As New LiveB2cDataContext
Try
db.Staff.InsertAllOnSubmit(lstStaff)
Next
db.SubmitChanges()
'Fix is that you need to return the objects you have added in the database back as json to kendo
strJson = JsonConvert.SerializeObject(lstStaff, Formatting.None)
WriteJson(strJson) ' Returning the objects added as json back to Kendo
Catch ex As Exception
ErrorLog(ex)
End Try
End Sub
Public Shared Sub WriteJson(strJson As String)
Try
HttpContext.Current.Response.Write(strJson)
HttpContext.Current.Response.Flush()
HttpContext.Current.ApplicationInstance.CompleteRequest()
HttpContext.Current.Response.SuppressContent = True
Catch ex As Exception
ErrorLog(ex)
End Try
End Sub
Fix is that you need to return the objects you have added in the database back as json to kendo
I'm not sure if this is part of your issue, but in your DataSource's schema model you specify that the ID is the field named "BonusId", but that field isn't specified in the array of fields.
I was having a simular issue.
I fixed it but making sure the id in the model is referring to a field:-
model: {
id: "Id",
fields: {
Id: { editable: false, type: "number" },
AnotherName: { editable: true, type: "string" },
AnotherId: { editable: true, type: "number" }
}
}
This may not solve the asker's problem, but hopefully might help someone with the same issue.
For us, this problem was being caused by errors being returned in JSON. Some required properties didn't have a value, but weren't related to the data we were displaying in the grid. Giving those properties a default value in the grid solved the issue.
You can view the JSON that's being returned by using Fiddler Web Debugging Tools.
I have a JsonStore configured like so:
var store = new Ext.data.JsonStore({
restful: true,
url: '/categories',
remoteSort: true,
idProperty: 'Id',
totalProperty: 'total',
root: 'results',
writer: new Ext.data.JsonWriter({
encode: false
}),
fields: [ 'Id', 'Name' ]
});
I grab some data from the server, then edit one of the records. When I tell the store to save, it sends this JSON back to the server:
{
"results":
{
"Name":"Trivial123",
"Id":2
}
}
The store is wrapping the JSON inside the results property (the root property configured on the store). However, the server expects this:
{
"Name":"Trivial123",
"Id":2
}
In other words, the serialized entity should be put directly in the response body, and not wrapped in a property. Does anyone know how I can configure the store to do this?
You need to override the data rendering function in the JsonWriter, like so:
var rootlessRenderFunction = function (params, baseParams, data) {
if (this.encode === true) {
Ext.apply(params, baseParams);
params = Ext.encode(data);
} else {
params.jsonData = data;
}
};
var myWriter = new Ext.data.JsonWriter({
encode: false,
writeAllFields: true
});
myWriter.render = rootlessRenderFunction;
var myStore = new Ext.data.JsonStore({
// ... various config values ...
writer: myWriter
});
This "rootlessRenderFunction" implementation is the same as the Ext JsonWriter's render code except it doesn't interpose a root in the request data.
This is a hack, of course.
I'm assuming you can't just not set the root value for the store for some reason? That's the way I normally do it.