vuejs2 reusable code in N tabs - duplicates

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/

Related

How do i iterate through JSON in VueJS?

I am storing some settings in the database with keys and JSON data but when I get these settings from a Laravel API, it returns an array which becomes a hectic work in reassigning data to the input fields. I want to know if there is an easier way of doing it.
So far I have tried iterating and using the switch statement to identify keys and reassign them. But the problem is I can't access the VueJS data variable in the loop.
Here is a look at the database table:
Database Table
Here are the objects I am using in Vue:
helpful_notification: {
email: false,
sms: false,
push: false,
},
updates_newsletter: {
email: false,
sms: false,
push: false,
},
Here is my Code to Iterate over results:
axios.get('/api/notificationsettings')
.then(response => {
var data = response.data;
let list = [];
console.log(data)
$.each(data, function(i, j){
switch(j.key){
case 'transactional':
var settings = JSON.parse(j.settings)
var x = {
transactional : settings
}
list.push(x)
break;
case 'task_reminder':
var settings = JSON.parse(j.settings)
x = {
task_reminder : settings
}
list.push(x)
break;
}
});
this.transactional = list;
// this.task_reminder= list.task_reminder;
console.log(list);
})
.catch(error => {
});
In JavaScript, functions have their own scope, save for a few exceptions. Which means that, inside your anonymous function (i.e:
$.each(data, function(i, j){
// this here is the function scope, not the outside scope
})
...), this is not the outside scope, it's the function's scope
There are two ways to make the outside scope available inside your function:
a) place it inside a variable
const _this = this;
$.each(data, function(i, j){
// this is function scope,
// _this is outside scope (i.e: _this.list.task_reminder)
})
b) use an arrow function
$.each(data, (i, j) => {
// this is the outside scope
// the arrow function doesn't have a scope.
})
The above is a simplification aimed at helping you access the outside scope inside your function. But this can differ based on the context it is used in. You can read more about this here.

backbone render collection return one object

i have problem rendering my view...the view return always the last in the json object: This is the code:
Router.js:
var list = new clientCollection();
var cards = new cardsView({model:list})
list.fetch({success: function (collection, response, options) {
cards.render();
}
});
Cards.js view:
....
tagName: 'section',
className: 'list',
template: Handlebars.compile(cardsTemplate),
render: function () {
var list = this.model.toJSON(),
self = this,
wrapperHtml = $("#board"),
fragment = document.createDocumentFragment();
$(list).each(function (index, item) {
$(self.el).html(self.template({card: item}));
$.each(item.cards, function (i, c) {
var card = new cardView({model : c});
$(self.el).find('.list-cards').append(card.render().el);
});
fragment.appendChild(self.el);
});
wrapperHtml.append(fragment.cloneNode(true));
},
...
This is my json data:
[
{"id":"9","name_client":"XXXXXXX","cards":[]},
{"id":"8","name_client":"XXXXXXX","cards":[{"id":"8","title":"xxxxx.it","description":"some desc","due_date":"2016-01-23","sort":"0"}]}
]
Can u help me to render the view?
It's hard to know for sure without seeing how the view(s) are attached to the DOM, but your problem appears to be this line ...
$(self.el).html(self.template({card: item}));
That is essentially rendering each element in the collection as the full contents of this view, then replacing it on each iteration. Try instead appending the contents of each template to the view's element.
Also, since you tagged this with backbone.js and collections, note that the easier, more Backbone-y way to iterate through a collection would be:
this.model.each(function(item) {
// 'item' is now an instance of the Backbone.Model type
// contained within the collection. Also, note the use
// of 'this' within the iterator function, as well as
// this.$el within a View is automatically the same as
// $(self.el)
this.$el.append(this.template({ card: item });
// ... and so on ...
// By providing 'this' as the second argument to 'each(...)',
// the context of the iterator function is set for you.
}, this);
There's a lot packed in there, so ...
Backbone.Collection Underscore Methods
Backbone.View this.$el

Populating a BackboneJS model with response from an API endpoint

I'm new to BackboneJS but I'm doing my best to learn it. I'm more familiar with AngularJS so I have some confusion in BackboneJS but would definitely want to become an expert BackboneJS developer too.
Back at my previous job, I was the frontend dev and I would work with the Java dev guy. We would have a meeting about how the JSON response would look like. Basically, I'll make a REST call(either with Restangular or $http) to one of their endpoints and I'll get a response. The JSON response will be assigned to a scope variable such as $scope.bookCollection. In my template, I'll just use ng-repeat to display it.
Now with BackboneJS, I'd like to do it properly. I read today that a BackboneJS Model is a container. What I'd like to happen is that after making a fetch(), I want the JSON response to be put in the Model that I defined. How is that done?
I found an example jsfiddle but I think it's a very bad example. I can't find something that is helpful right now, something with a good fetched data.
require.config({
paths: {
jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min',
underscore: 'http://underscorejs.org/underscore',
backbone: 'http://backbonejs.org/backbone-min'
},
shim: {
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
underscore: {
exports: "_"
}
}
});
require([
'jquery',
'underscore',
'backbone'], function ($, _, Backbone) {
var UserModel = Backbone.Model.extend({
urlRoot: '/echo/json/',
defaults: {
name: '',
email: ''
}
});
var userDetails = {
name: 'Nelio',
email: 'nelio#angelfire.com'
};
var user = new UserModel(userDetails);
user.fetch({
success: function (user) {
console.log(user.toJSON());
}
});
});
Here is the jsfiddle:
http://jsfiddle.net/20qbco46/
I want the JSON response to be put in the Model that I defined. How is
that done?
If you are trying to render the data from you model, you will use a view for this:
First, create a view to render your data:
// Create a new view class which will render you model
var BookView = Backbone.View.extend({
// Use underscores templating
template: _.template('<strong><%= title %></strong> - <%= author %>'),
initialize: function() {
// Render the view on initialization
this.render();
// Update the view when the model is changed
this.listenTo(this.model, "change", this.render);
},
render: function() {
// Render your model data using your template
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
See also: template and toJSON as well as $el
Next, create a Model:
// Create a model class
var Book = Backbone.Model.extend({
urlRoot: '/echo/json/',
defaults: {
title : '',
author: ''
},
});
Your model will hold the data fetched from the url / urlRoot
You can use set if you are trying to add new attributes to your model.
You can use get to grab attributes from your model.
See also - save and destroy.
Then, instantiate your model:
// Some dummy data
var instance = {
title: 'learn Backbone JS',
author: 'Bobby Longsocks',
};
// Instansite your model
var model = new Book(instance);
And finally, fetch your model data and create a new instance of you view:
// Fetch your model
model.fetch({
success: function(book) {
// Instansite your view, passing in your model
var view = new BookView({model: book, el: $('body')});
}
});
Here is an Example you can fiddle with.
And some further reading: Annotated Source

DOJO: Dynamic creation/Loading/fetching of trees

I want to load a tree structure in dojo dynamically with every layer loading(fetching data from server) only after a click to the next layer is made. This would help me to not have the entire tree loaded in memory all together but as someone clicks a level of a tree, only then all the elements of the next level are fetched from the server using ajax requests in dojo.
Can someone help me on how to go about this?
The answer for this is here as follows: using a dijit tree, it has just 3 steps to create a dynamic tree that loads lazily: 1. Create a store, 2. Create a model, 3. Create the tree. Here is the code snippet that I used which worked perfectly:
function createLazyTreeStore()
{
var store = new JsonRest({
target: "location where your file is",
getChildren: function(object) {
// object may just be stub object, so get the full object first and then return it's
// list of children
return this.get(object.id).then(function(fullObject){
console.log(fullObject.children);
return fullObject.children;
});
}
});
return store;
}
function createModel(store)
{
var model = new ObjectStoreModel({
store: store,
getRoot: function(onItem) {
this.store.get("the .php file").then(function(item)
{
onItem(item[0]);
});
},
getChildren: function(object, onComplete, onError)
{
this.store.get("your url to fetch the data with parent child relation").then(function(fullObject) {
object.children = fullObject;
onComplete(object.children);
}, function(error)
{
console.error(error);
onComplete([]);
});
},
mayHaveChildren: function(object) {
return true;
}
});
return model;
}
function createTree(model)
{
var tree = new Tree({
model: model,
style: "your preference",
id: "tree",
});
return tree;
}
Then call these functions in the following order:
var store = createLazyTreeStore();
var model = createModel(store);
var tree = createTree(model);
accordionPane.addChild(tree);

scopes and directives in AngularJs

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.