I am having trouble getting the knockoutjs checked binding to work properly. Not sure if I'm just doing something wrong or what. I have this piece of html
<ul data-bind="foreach: ListItems" >
<li style="padding-left: 0px; margin-left: 0px; color: white; font-size: 12px;">
<div class="title" style="margin-right: 3em; line-height: 20px;">
<input type="checkbox" data-bind="checked: IsActive" />
<label data-bind="text: Quantity, disable: IsActive"</label>
<label data-bind="text: Description, disable: IsActive" ></label>
</div>
</li>
</ul>
Where I want a checkbox that allows users to mark items off this list by clicking the checkbox which should either strikeout the text or grey it out or something.
My view model is created by getting the following json data format.
{"$id":"1","Description":"New List","Categories":
[{"$id":"2","Description":"Bread/Bakery","ListItems":
[{"$id":"3","IsActive":1,"Description":"Bread","Quantity":"1 Loaf"}]},
{"$id":"4","Description":"Beverages","ListItems":
[{"$id":"5","IsActive":1,"Description":"Coke","Quantity":"1 Case"},
So the problem is that checking the checkbox doesn't actually do anything here. It should be disabling the other labels but it doesn't. All my other values are displayed correctly and if I do a data-bind=text: IsActive I can see the value that should be changing with the checkbox but it never changes.
Edit: following suggestion below:
var mydata = ko.observableArray([
{
Categories: ko.observableArray([
{
Description: "Dairy", ListItems: ko.observableArray([
{ Description: "Eggs", Quantity: "1 Dz.", IsActive: ko.observable(false) },
{ Description: "Milk", Quantity: "1 Gallon", IsActive: ko.observable(false) }
])
},
{
Description: "Produce", ListItems: ko.observableArray([
{ Description: "Lettuce", Quantity: "1 Head", IsActive: ko.observable(false) },
{ Description: "Oranges", Quantity: "5 ea.", IsActive: ko.observable(false) },
{ Description: "Greenbeans", Quantity: "1 Thingy", IsActive: ko.observable(false) },
])
},
])
}
]);
The issue you are having is because your data is a plain JSON object and that will get bound only once.
To get the bidirectional binding behaviour you are looking for, your objects need to be "observables", so for example:
var mydata = ko.observable({
Categories: ko.observableArray([
{ IsActive: ko.observable(true) }
])
});
Note that it is up to you to determine which items in your structure need to be observables; it will depend on how you want the bindings to behave.
Related
I have a scenario where i want to get the name from the multiple selected checked boxes and display divs based on the selected checkbox.
Issue: I have 4 checkboxes and and I want to display divs based n the selected checkbox. these checkboxes are multiple, so can select multiple checkbox and get the multiple ids.
Here is the HTML code that I have done to achieve it:
<b-row>
<div v-for="services in getServices" :key="services.id">
<input
type="checkbox"
multiple
:name="services.name"
v-model="selected"
:value="{ name: services.name, id: services.id }"
/>
<label :for="services.name">{{ services.name }}</label>
</div>
</b-row>
{{selected}}
i have this also in the script side:
return {
selected: [],
}
Current issue:
I cannot get only id /name in the selected section. if I can get it , I can show the divs based on that. but I need to have the ids also while I want to save/post
Change the value of the checkbox to only name or id as follows for example and base it on that
<input
type="checkbox"
multiple
:name="services.name"
v-model="selected"
:value="services.id"
/>
<div v-if="getNameFromId(selected[0]) == 'div1'">This is div1.</div>
methods: {
getNameFromId: function (id) {
return this.getServices.find(service => service.id === id).name;
}
}
Add a property to array:
<div v-for="service in services" :key="service.id">
<input
type="checkbox"
multiple
:name="service.name"
v-model="service.selected"
:value="{ name: service.name, id: service.id }"
/>
<label :for="services.name">{{ service.name }}</label>
</div>
{{ selectedServices }}
And in the script:
export default {
name: "component",
data: function () {
return {
selected: [],
services: [
{
id: 1,
name: "Pedro",
selected: false,
},
{
id: 2,
name: "Jose",
selected: false,
},
],
};
},
computed: {
selectedServices: function () {
return this.services.filter((item) => item.selected);
},
},
};
This worked fine for me.
New to VueJS. I am trying to build a custom ul component for a webpage that can be populated and updated via custom props (preferably string, but doesn't have to be), specifically in the HTML so that any other dev can simply use/update/add to the custom component with said prop, and it will add a new li through the addition of a second, third, fourth, etc. prop, appending the previous li. I am also struggling to see if more than one input type can be used on a custom prop. For a better explanation heres a coded example of what I currently have and what I would like to do:
Vue.component('resources', {
template: `
<!-- Resources Component -->
<div class="resources">
<div class="heading">
<p>Resources</p>
</div>
<ul class="resource-list">
<li v-for="item in items">
<a :src="item[source]">{{ item.message }}</a>
</li>
</ul>
</div>
`,
props: {
source: {
type: String,
default: "."
},
message: {
type: String
}
},
data () {
return {
items: [
{
message: {
type: String
},
source: {
type: String,
default: "."
}
}
]
}
}
});
And in my HTML the component looks like this:
<helpful-resources
message="test"
source="."
></helpful-resources>
This 1000% has a lot of issues, but ideally I would like to have something along the lines of this:
<helpful-resources
item: src="example url 1" message="test message 1"
item: src="example url 2" message="test message 2"
></helpful-resources>
With every addition of a new 'item' appending the previous list item with a new one with the ability to change the src and the message over and over again as needed for however many items are needed in the list.
Any help/clarification would be greatly appreciated. Thanks!
In the parent component:
<template>
<div class="resources">
<div class="heading">
<p>Resources</p>
</div>
<Helpful-resources :listItems="listItems"></Helpful-resources>
</div>
</template>
<script>
#import HelpfulResources from '#/path/to/HelpfulResources';
export default {
name: 'Resource',
components: {
HelpfulResources
},
data() {
return {
listItems: [
{src: 'link to item', message: 'special message'},
{src: 'link to item2', message: 'special message2'},
// More items ...
]
}
}
}
</script>
<style lang="scss">
/* styles */
</style>
Your component could be structured like this:
Helpful-resources.vue
<template>
<ul class="resource-list">
<li v-for="(item, index) in listItems" :key="'listItem-'+index">
<a :href="item.src">{{ item.message }}</a>
</li>
</ul>
</template>
<script>
export default {
name: 'helpful-resource',
props: [ 'listItems'],
data() {
return {
// More data ...
}
}
}
</script>
<style lang="scss">
/* styles */
</style>
Note this is styled in the vue-cli fashion, but you can modify it to fit your needs.
EDIT
To include it within an html file you would place your Vue components within the body, script tags just below the body tag.
<div id="app">
<resources :source="someData" :message="message" id="r"></resources>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.10/dist/vue.js"></script>
<script>
let resources = Vue.component('resources', {
template: `<div class="resources">
<div class="heading"><p>Resources</p></div>
<ul class="resource-list">
<li v-for="(item, index) in items" :key="index"><a :href="source">{{ item.message }}</a></li>
</ul>
</div>`,
props: {
number: Number,
source: {
type: String,
default: "."
},
message: {
type: String,
default: 'No message'
},
// Example of multiple data types
propB: [String, Number]
},
data() {
return {
items: [
{
message: this.message,
source: this.source
}
]
}
}
});
new Vue({
el: '#app',
components: {
resources
},
data: {
someData: 'path/to/source',
message: 'Special Message'
},
});
</script>
Here's a link to the fiddle anyways...Fiddle
As far as updating the list goes, you could use an API call to get data asynchronously or allow users to add info via button or input and use a method. Or if you are talking strictly hardcoding extra values, other developers would add to your file...
Hopefully this helps. If not, please clarify.
I have a form like this
<div class="warranty-part">
<paper-input maxlength="4" name="warranty[0]" no-label-float label="1111" value="{{warranty0::input}}"></paper-input>
</div>
<div class="warranty-part">
<paper-input maxlength="4" name="warranty[1]" no-label-float label="1111" value="{{warranty1::input}}"></paper-input>
</div>
<div class="warranty-part">
<paper-input maxlength="4" name="warranty[2]" no-label-float label="1111" value="{{warranty2::input}}"></paper-input>
</div>
<div class="warranty-part">
<paper-input maxlength="4" name="warranty[3]" no-label-float label="1111" value="{{warranty3::input}}"></paper-input>
</div>
With four different fields. Each of these input values is bound to one property defined like...
properties: {
warranty0: {
type: String,
observer: 'onWarrantyChange0'
},
warranty1: {
type: String,
observer: 'onWarrantyChange1'
},
warranty2: {
type: String,
observer: 'onWarrantyChange2'
},
warranty3: {
type: String,
observer: 'onWarrantyChange3'
}
}
This works... but what would be tidier is to be able to bind to array values for each of the fields to tidy things up.
Like
properties: {
warranty: {
type: Array,
value: ['','','',''],
observer: 'onWarrantyChange'
}
}
But I just can't work out how to bind to an index of an array with polymer. From reading the docs I got the impression that binding to the input value like this would work...
value="{{warranty.0::input}}"
But it doesn't.
Is there any way to do this?
Try {{warranty.0}}, {{warranty.1}}, etc..
But if you update any of the paper-input's value, the onWarrantyChange observer won't be called as you will need a special * syntax for property change notification inside an array (See this).
properties: {
warranty: {
type: Array,
value: ['111','222','333','444']
}
},
observers: ['onWarrantyChange(warranty.*)'],
onWarrantyChange: function (changedWarranty) {
console.log(changedWarranty);
}
See this plunker for reference.
Update
Looks like the Polymer could be confused by bindings of valued type string literals. So a simple workaround would be to define an array with 4 objects like this -
value: [ { value: '' }, { value: '' }, { value: '' }, { value: '' } ]
And the bindings will become -
value="{{warranty.0.value}}", value="{{warranty.1.value}}", etc..
See this new plunker.
So, just getting started in Angular and it's pretty tricky, coming from a pretty simple JS and jQuery background. Here's what I'm trying to do. I have a "tag template" that has a couple categories and then some sub-tags contained within. I have defined these as an object, with the idea that the object/file can be called via file request and manipulated, etc.
I have loaded labels and tag category inputs dynamically by using a factory service and a controller with ng-repeat. Likewise, I have deposited the subtags into another div on page2 (using jQuery mobile page swiping). I'd like to use the checkbox state of the category tags to show/hide the sub-tags on page2.
I have tried dozens of things and searched all over stackexchange, the net, etc, but is simple and straightforward and similar enough for me to get it working. If someone can point me in the right direction, that would be great. Keep in mind that my next step is to add a button on page 1 to add a new category, and buttons on page 2 to add sub-tags to the sub-tag categories.
Finally, I have one more weird thing to report. If I only have two pages in my DOM, I have some weird behavior when loading the page. If I load from page 1, the tag checkboxes do not function, and I see a slight fattening of the border of the labels. If I swipe left to page 2 and reload from this page, the borders of the labels are thin and the checkboxes function. Cannot track down why this would be happening. My hacky workaround is to add an empty page zero and then changepage immediately to page one, but this is far from ideal. Any thoughts on that would be appreciated as well.
Here it is:
HTML
<!-- Angular version -->
<button class="ui-btn" onclick="selectTemplate();">My Template</button>
<form>
<div data-role="controlgroup">
<fieldset data-role="controlgroup">
<div ng-controller="templateCtrl">
<label
class="ui-checkbox"
ng-style="{backgroundColor: '{{tagCat.color | bgColor}}'}"
ng-repeat="tagCat in template"><input type="checkbox"
class="ui-checkbox"
id="{{tagCat.name}}"
ng-model="clicked"
ng-click="click();"
/>{{tagCat.name}}</label>
<div ng-repeat="tagCat in template">{{cb}} {{tagCat.name}} hallo</div>
</div>
</fieldset>
</div>
<div style="display:none" class="flashNotification"></div>
</form>
</div>
<div data-role="page" id="two">
<button class="ui-btn" onclick="selectTemplate();">My Template</button>
<form>
<div data-role="controlgroup">
<div ng-controller="templateCtrl">
<div ng-repeat="tagCat in template" ng-show="clicked" class="{{tagCat.name}}">{{tagCat.name}}
<fieldset data-role="controlgroup">
<label class="ui-checkbox"
ng-repeat="item in tagCat.items"
ng-style="{backgroundColor: '{{tagCat.color | bgColor}}'}"
for="item.name">{{tagCat.color | bgColor}}
<input class="ui-checkbox"
name="{{item.name}}"
id='{{item.name}}'
type="checkbox" />{{item.name}}</label>
</fieldset>
</div>
</div>
</div>
<div style="display:none" class="flashNotification"></div>
</form>
</div>
</div>
JS for jQuery Mobile
$(document).ready(function() {
// addTemplateItems(tagTemplate); // not necessary with Angular
// $.mobile.changePage('#two', { transition: 'none' }); // required or checkboxes don't work on load
$.mobile.changePage('#one', { transition: 'none' });
// // $("[data-role=controlgroup]").controlgroup("refresh");
// set up page nav
$(document).delegate('.ui-page', "swipeleft", function(){
var $nextPage = $(this).next('[data-role="page"]');
var $prevPage = $(this).prev('[data-role="page"]');
console.log("binding to swipe-left on "+$(this).attr('id') );
// swipe using id of next page if exists
if ($nextPage.length > 0) {
$.mobile.changePage($nextPage, { transition: 'slide' });
} else {
var message = 'tagged!';
// save tags here
flashNotify(message);
console.log('fire event!');
$('#flashNotification').promise().done(function () {
$('#group1').hide();
$('#group2').hide();
$('.ui-btn').hide();
// addTemplateItems(tagTemplate);
$.mobile.changePage($prevPage, { transition: 'none' });
captureImage();
});
}
}).delegate('.ui-page', "swiperight", function(){
var $prevPage = $(this).prev('[data-role="page"]');
console.log("binding to swipe-right on "+$(this).attr('id') );
// swipe using id of next page if exists
if ($prevPage .length > 0) {
$.mobile.changePage($prevPage, { transition: 'slide', reverse : true });
} else {
alert('no backy backy!');
}
});
// $("input[type='checkbox']").checkboxradio().checkboxradio("refresh");
});
JS for Angular App
var app = angular.module('STL', []);
app.factory('TagTemplate', [function () {
var TagTemplate = {};
var tagTemplate = {
family: {
name: "family",
description: "These are your family members.",
color: "red",
items: [
{
name: "Joe"
},
{
name: "Mary"
},
{
name: "Jim"
}
]
},
design: {
name: "design",
description: "Different types of design notes.",
color: "blue",
items: [
{
name: "inspiring"
},
{
name: "fail"
},
{
name: "wayfinding"
},
{
name: "graphics"
}
]
},
work: {
name: "work",
description: "Stuff for work.",
color: "green",
items: [
{
name: "whiteboard"
},
{
name: "meeting"
},
{
name: "event"
}
]
}
};
TagTemplate = tagTemplate;
return TagTemplate;
}])
// Controller that passes the app factory
function templateCtrl($scope, TagTemplate) {
$scope.template = TagTemplate;
$scope.click = function(model) {
console.log(this.checked, this.tagCat.name);
}
}
app.filter('bgColor', function () {
return function (color) {
// console.log(color, $.Color(color).lightness(.05).toHexString(.05));
// var rgba = $.Color(color).alpha(.05);
return $.Color(color).lightness(.97).toHexString();
}
})
For the main part, success!
I found a jsfiddle that gave me a good base for experimenting. After some playing, I realized that I just have to create a show property within each of the categories in my data service model, and then assign the ng-model to that property to control it.
I had to do it slightly differently in my own code, but the understanding gained from the following jsfiddle led me to the answer:
http://jsfiddle.net/Y43yP/
HTML
<div ng-app ng-controller="Ctrl">
<div class="control-group" ng-repeat="field in customFields">
<label class="control-label">{{field}}</label>
<div class="controls">
<input type="text" ng-model="person.customfields[field]" />
<label><input type="checkbox" ng-model="person.show[field]" /></label>
</div>
</div>
<button ng-click="collectData()">Collect</button><button ng-click="addField()">Add Field</button><br/><br/>
<em>Booleans</em>
<div ng-repeat="field in customFields">
<p>{{field}}: {{person.show[field]}}</p>
</div>
<em>Show/Hide</em>
<div ng-repeat="field in customFields">
<p ng-show="person.show[field]">{{field}}: {{person.customfields[field]}}</p>
</div>
</div>
JS
function Ctrl($scope) {
$scope.customFields = ["Age", "Weight", "Height"];
$scope.person = {
customfields: {
"Age": 0,
"Weight": 0,
"Height": 0
},
show: {
"Age": false,
"Weight": false,
"Height": false
}
};
$scope.collectData = function () {
console.log($scope.person.customfields, $scope.person.show);
}
$scope.addField = function () {
var newField = prompt('Name your field');
$scope.customFields.push(newField);
}
}
Still having the checkbox issue but I'll open a separate issue for that if I can't figure it out.
Thanks.
I have this pure code in HTML
<body style="margin:0px; padding:0px;" onload="load()">
<div>
<input type="text" id="addressInput" size="10"/>
<select id="radiusSelect">
<option value="25" selected>25mi</option>
<option value="100">100mi</option>
<option value="200">200mi</option>
</select>
<input type="button" onclick="searchLocations()" value="Search"/>
</div>
<div><select id="locationSelect" style="width:100%;visibility:hidden"></select></div>
<div id="map" style="width: 100%; height: 80%"></div>
</body>
what i am trying in sencha Touch 2 is
items: [{
xtype: 'fieldset',
title: 'Search Stores',
items: [
{
xtype: 'textfield',
name : 'name',
label: 'Adress',
placeHolder: 'Enter City & State or ZIP code'
},
{
xtype: 'selectfield',
label: 'Radius:',
options: [
{text: '25mi', value: '25'},
{text: '100mi', value: '100'},
{text: '200mi', value: '200'}
]
}
]
}]
Actually I am working on finding the store using sencha touch 2 and i follow this link
https://developers.google.com/maps/articles/phpsqlsearch_v3
this works fine for me but this code is not sufficient, now i want to know how can i call this from sencha touch 2 onload="load(), onclick="searchLocations()", visibility:hidden
I read the documentation of sencha touch but not able to do that any help is highly appreciated
Here's equivalent code of your HTML in Sencha touch
<input type="button" onclick="searchLocations()" value="Search"/>
{
xtype: 'button',
text: 'Search',
ui: 'confirm',
listeners : {
tap : function() {
// body of searchLocations()
}
}
}
For visibility:hidden, use the following property of selectfield
hidden: true
For onload="load()", you can call following method of Component.
initialize()