Two-way binding doesn't work inside Ractive.components - ractivejs

I want to divide layout for some components and i used Ractive.components for it.
All data are correct in component and used in it (like id and color).
But variable for two-way binding don't used correct.
I have one javascript behavior and three html layouts, and two layout from them don't work.
JS behavior
var config = [
{id: 1, color: '#cc8'},
{id: 2, color: '#c88'},
{id: 4, color: '#8c8'},
{id: 8, color: '#8cc'}
];
var Panel = Ractive.extend({
el: document.body,
template: '#panel',
data: function() {
return {
config: config,
filters: [4,8]
};
},
components: {
switcher: function() {return 'Switcher';}
}
});
var Switcher = Ractive.extend({
template: '#switcher'
});
Ractive.components.Switcher = Switcher;
var panel = new Panel();
HTML layout 1 (doesn't work)
<script id="panel" type="text/ractive">
<h4>Doesn't work: {{filters}}</h4>
{{#each config}}
<switcher name="{{filters}}">
filter #{{id}}
</switcher><br/>
{{/each}}
<br/>
</script>
<script id="switcher" type="text/ractive">
<label
class="switcher"
style="color:{{color}};">
<input
type="checkbox"
value={{id}}
name={{name}}
class="switcher__input">{{>content}}
</label>
</script>
HTML layout 2 (doesn't work)
<script id="panel" type="text/ractive">
<h4>Doesn't work too ("~/"): {{filters}}</h4>
{{#each config}}
<switcher name="{{~/filters}}">
filter #{{id}}
</switcher><br/>
{{/each}}
<br/>
</script>
<script id="switcher" type="text/ractive">
<label
class="switcher"
style="color:{{color}};">
<input
type="checkbox"
value={{id}}
name={{name}}
class="switcher__input">{{>content}}
</label>
</script>
HTML layout 3 (work)
<script id="panel" type="text/ractive">
<h4>Work: {{filters}}</h4>
{{#each config}}
<label
class="switcher"
style="color:{{color}};">
<input
type="checkbox"
value={{id}}
name={{filters}}
class="switcher__input">
tags #{{id}}
</label><br/>
{{/each}}
</script>
And live demo
How to make right Ractive.component with two-way binding?
P.S. Sorry for my English..

Related

Assign value to input without v-model and without databinding

In my v-for i need to initialize some input field with some text WITHOUT binding it to the object. Currently i'm trying:
<div v-for="item in allItems">
<input type="text" class="header-title" value="item.name"></input>
</div>
but item.name is printed in the input instead of the item name. How to accomplish this?
v-model is just syntactic sugar for :value and an event, usually #input. See docs here.
You can pass a noop function () => {} to cancel the value update or do whatever you want with the new value, maybe assign it to another object.
Note: <input> elements are void, they do not require a closing tag.
new Vue({
el: '#app',
data() {
return {
allItems: [{ name: 'foo' },{ name: 'bar' }]
}
},
})
<script src="https://unpkg.com/vue#2.5.9/dist/vue.js"></script>
<div id="app">
<div v-for="item in allItems">
<input type="text" class="header-title" :value="item.name" #input="() => {}">
{{ item.name }}
</div>
</div>
You can have your input show value of item.value by only using the ref attribute.
Just add ref='' and map it's values to the inputs value, inside your mounted function.
new Vue({
el: '#app',
data () {
return {
allItems: [
{name: 'foo'},
{name: 'bar'}
]
}
},
mounted () {
let self = this;
this.$refs.inp.map( (m, k) => {
m.value = self.allItems[k].name
})
}
})
<script src="https://unpkg.com/vue#2.5.9/dist/vue.js"></script>
<div id="app">
<div v-for="item in allItems">
<input type="text" class="header-title" value="item.name" ref='inp'></input>
</div>
</div>

Uploaded Images is being deleted when meteor js restarts

I'm still new to Meteor. I'm creating a Meteor JS project and one of the central features of it is image upload or more like a featured image upload. The upload works fine and after clicking on submit it will show on my <div class="viewing">. The problem occurs when you restart Meteor. The image will be deleted and thus no image is displayed by the time I run the program.
Here's my code:
The HTML:
<body>
{{> viewPost}}
<h1>Welcome to Meteor!</h1>
{{> addPost}}
</body>
<template name="addPost">
<form class="main-form">
<input type="text" name="title"/>
<br><br>
<input type="file" name="imgUp" class="fileIn"/>
<br><br>
<button>Submit</button>
</form>
</template>
<template name="viewPost">
{{#each images}}
<div class="viewing">
<img src="{{this.url store='images'}}"/>
</div>
{{/each}}
</template>
JS:
Images = new FS.Collection("images", {
stores: [new FS.Store.FileSystem("images",{path: "~/uploads"})],
filter: {
allow: {
contentTypes: ['image/*'] //allow only images in this FS.Collection
}
}
});
if (Meteor.isClient) {
Template.addPost.events({
'submit .main-form': function(event, template){
var title = event.target.title.value;
event.preventDefault();
var fileObj = template.find('input:file');
Images.insert(fileObj.files[0], function (err,fileObj){});
}
});
Template.viewPost.helpers({
images: function(){
return Images.find({});
}
});
}
Please tell me what I am doing wrong here. Any help would be great! I've been looking for a way to solve this for a few days already.

Not doing anything in function to close the panel

<div class="close" on-click='close'></div>
Ractive.components['block:close'] = Ractive.extend({
isolated: true,
onrender: function() {
this.on({
close : function(event) {
console.log('close');
}
})
}
});
When trying to click on the 'x' button, it doesn't show "close" in console.log.
Not sure why it is not doing anything.
Also looked up ractivejs on google for the animation (fade out) when click close. Couldn't find a way without using JQuery
Not quite sure what's going on in your example - this works fine!
Ractive.components['block:close'] = Ractive.extend({
isolated: true,
template: '<div class="close" on-click="close">click me</div>',
onrender: function() {
this.on({
close: function(event) {
alert('it works');
}
});
}
});
var ractive = new Ractive({
el: 'main',
template: '<block:close/>'
});
<script src='http://cdn.ractivejs.org/latest/ractive.js'></script>
<main></main>
To add fades and other transitions, you need to use transition plugins. For example:
new Ractive({
el: 'main',
template: '#template'
});
<script src='http://cdn.ractivejs.org/latest/ractive.js'></script>
<script src='https://rawgit.com/ractivejs/ractive-transitions-fade/master/dist/ractive-transitions-fade.js'></script>
<main></main>
<script id='template' type='text/html'>
<label>
<input type='checkbox' checked='{{visible}}'>
visible (click me)
</label>
{{#if visible}}
<div intro='fade'>this will fade in</div>
{{/if}}
</script>
See the ractive-transitions-fade GitHub repo for more info.

Show loading indicator on partial template

I have the following template
<template name="myTabs">
<div class="my-tabs">
<div class="page-header">
<h1>My Tabs</h1>
</div>
<form class="navbar-form navbar-left" role="search">
New
<div class="form-group">
<input type="text"
name="tab"
class="form-control typeahead"
autocomplete="off" spellcheck="off"
data-source="tabs"
data-template="tabSearch"
placeholder="Filter"/>
</div>
</form>
{{>tabsTable}}
</div>
</template>
And the following nested template
<template name='tabsTable'>
<table class="table table-hover">
... table that displays data from collection
</table>
</template>
And the following route
this.route('myTabs', {
path: '/mytabs',
layoutTemplate: 'dashboardLayout',
loginRequired: 'entrySignIn',
waitOn: function() {
return this.subscribe("mytabs", Meteor.userId());
},
data: {
tabs: Tabs.find({})
},
onAfterAction: function() {
SEO.set({
title: 'My Tabs | ' + SEO.settings.title
});
}
});
Problem is that when i visit the myTabs route, the whole template is replaced by the loading template, instead of just the part that depends on the collection being loaded, namely the tabsTable template.
How can I make it so that the loading template is only displayed on the nested template, so that all the html that doesnt depend on the collection being loaded is still shown (title, wrapping html etc..)?
Instead of using waitOn with a loadingTemplate in the router, you can use subscriptions which will give you a ready calllback which you can use to hide the loading template in your view.
Router.route('myTabs', {
path: '/mytabs',
layoutTemplate: 'dashboardLayout',
loginRequired: 'entrySignIn',
subscriptions: function() {
this.subs = Meteor.subscribe("mytabs", Meteor.userId());
},
data: function() {
return {
tabs: Tabs.find(),
ready: this.subs.ready
};
},
onAfterAction: function() {
SEO.set({
title: 'My Tabs | ' + SEO.settings.title
});
}
});
Then in your view
<template name="myTabs">
<div class="my-tabs">
<!-- ... -->
{{#unless ready}}
{{> loadingTemplate}}
{{else}}
{{> tabsTable}}
{{/unless}}
</div>
</template>

Data binding not working but works fine in tutorial

I am new to knockout.js. I am following this tutorial. It is working fine on knockout site but not for me. Error console is also not showing any error.
Below is my code
View:
Tasks
<form data-bind="submit: addTask">
Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" />
<button type="submit">Add</button>
</form>
<div >
<ul data-bind="foreach: tasks, visible: tasks().length > 0" id="testing">
<li>
<input type="checkbox" data-bind="checked: isDone" />
<input data-bind="value: title, disable: isDone" />
Delete
</li>
</ul>
</div>
View Model:
<script>
function Task(data) {
this.title = ko.observable(data.title);
this.isDone = ko.observable(data.isDone);
}
function TaskListViewModel() {
// Data
var self = this;
self.tasks = ko.observableArray([]);
self.newTaskText = ko.observable();
self.incompleteTasks = ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(), function(task) { return !task.isDone() });
});
// Operations
self.addTask = function() {
self.tasks.push(new Task({ title: this.newTaskText() }));
self.newTaskText("");
};
self.removeTask = function(task) { self.tasks.remove(task) };
}
ko.applyBindings(new TaskListViewModel(),document.getElementById("testing"));
</script>
The problem is that the ko.applyBindings doesn't apply to all data-bind attributes. Move your "testing" id to a place where it covers all the HTML code with the relevant "data-bind" attributes.

Resources