The application is written using ASP.NET MVC 3 in vs2010.
I have a knockout template that updates some css and visible bindings using a
dependantObservable.
The issue ONLY occurs when I bind the
value of the select element to the
IntervalID. If this is not bound the
UI is updated as expected.
I have ripped the code out from my main app and created a sample page that does the same binding using standard markup and also templates.
The dependantObservable is called HasChanged.
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="../../Scripts/jquery.tmpl.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-1.2.0.js" type="text/javascript"></script>
<div data-bind="template: { name: 'intervalTemplate', for:viewModel }">
</div>
<h2>
Not Template</h2>
<div data-bind="style: { color: HasChanged() ? 'red' : 'black' }">
IntervalID: <span data-bind="text: IntervalID"></span>
<br />
Start:
<input type="text" data-bind="value: Start">
<br />
End:
<input type="text" data-bind="value: End">
<br />
Interval Type:
<select data-bind="value: IntervalTypeID">
<option value="1">Shift</option>
<option value="2">Break (Paid)</option>
<option value="3">Break (Unpaid)</option>
</select><br />
HasChanged: <span data-bind="text: HasChanged"></span>
</div>
<script id="intervalTemplate" type="text/html">
<div data-bind="style: { color: HasChanged() ? 'red' : 'black' }">
<h2>Template</h2>
IntervalID: <span data-bind="text: IntervalID"></span>
<br />
Start:
<input type="text" data-bind="value: Start">
<br />
End:
<input type="text" data-bind="value: End">
<br />
Interval Type:
<select data-bind="value: IntervalTypeID">
<option value="1">Shift</option>
<option value="2">Break (Paid)</option>
<option value="3">Break (Unpaid)</option>
</select><br />
HasChanged: <span data-bind="text: HasChanged"></span>
</div>
</script>
<script type="text/javascript">
function IntervalModel(data) {
var _this = this;
_this.IntervalID = ko.observable(data.IntervalID);
_this.Start = ko.observable(data.Start);
_this.End = ko.observable(data.End);
_this.IntervalTypeID = ko.observable(data.IntervalTypeID);
_this.OriginalStart = ko.observable(data.Start);
_this.OriginalEnd = ko.observable(data.End);
_this.OriginalIntervalTypeID = ko.observable(data.IntervalTypeID);
_this.HasChanged = ko.dependentObservable(function () {
return !(_this.OriginalStart() == _this.Start() &
_this.OriginalEnd() == _this.End() &
_this.OriginalIntervalTypeID() == _this.IntervalTypeID());
});
}
var viewModel;
$(function () {
var viewModel = {};
viewModel = new IntervalModel({ IntervalID: 1, Start: "09:00", End: "10:00", IntervalTypeID: 2 });
ko.applyBindings(viewModel);
});
</script>
Any help would be much appreciated... I need to use templates as i have lots of these intervals that need to be displayed.
Thanks!
There is an issue logged on github for this one here: https://github.com/SteveSanderson/knockout/issues/133
The issue centers around using numbers for the value of a select option. When a select element uses the value binding, it is updated with the actual value of the element, which is always a string. So, if your observable is 2, it gets set to "2" when the binding is set up. This change seems to cause an issue with any bindings that use that observable that were set up in the template prior to the select element.
So, until this is potentially fixed, you can make it work by passing IntervalTypeID as a string ("2"). An easy way to convert a number to string is to do yourvalue + ''.
Here it is working:
http://jsfiddle.net/rniemeyer/uDSFa/
Related
What I would like to do is:
When the checkbox is checked ---> change text value to "Yes" and store its value to a component variable
When the checkbox is unchecked ---> change text value to "No" and also store its value to a component variable
Below is the example that I excepted to have but this example uses Javascript.
I would like to implement the same behavior using livewire or/and alpinejs.
function myFunction() {
var checkBox = document.getElementById("toogleA");
var text = document.getElementById("text");
if (checkBox.checked == true) {
document.getElementById("text").innerHTML = "YES";
} else {
document.getElementById("text").innerHTML = "NO";
}
}
/* Toggle A */
input:checked~.dot {
transform: translateX(100%);
background-color: #7456e3;
}
/* Toggle B */
input:checked~.dot {
transform: translateX(100%);
background-color: #7456e3;
}
<link href="https://unpkg.com/tailwindcss#^2/dist/tailwind.min.css" rel="stylesheet" />
<!--Start toggle button-->
<div class="flex items-center justify-center w-auto mb-5">
<!-- label -->
<label for="toogleA" class="flex items-center cursor-pointer">
<!-- toggle -->
<div class="relative">
<!-- input -->
<input wire:model="person" id="toogleA" onclick="myFunction()" type="checkbox" name="test" value="person" class="sr-only" />
<!-- line -->
<div class="w-10 h-4 bg-gray-400 rounded-full shadow-inner"></div>
<!-- dot -->
<div class="absolute w-6 h-6 transition bg-white rounded-full shadow dot -left-1 -top-1"></div>
</div>
<div id="text" class="ml-3 font-medium text-gray-700">NON </div>
</div>
</div>
You can achieve this with just Livewire.
Component
class YourComponent extends Component
{
public bool $toggleA = false;
public function render()
{
return view('livewire.your-component');
}
}
Component view
<label for="toggleA">Toggle</label>
<input wire:click="$toggle('toggleA')" type="checkbox" id="toggleA" />
<p>{{ $toggleA ? 'Yes' : 'No' }}</p>
The $toggle function is a special helper in Livewire specifically for toggling the value of boolean properties.
Given an output prediction of shape [1,21,388,88] from my Unet. How can I plot it as a masked image? I am using PASCAL dataset.
Thanks!
Basically you can do something like this and give conditional so when they meet requirements you get the style/ image you want
<template>
<menu>
<router-link to="/">
<li>
<div :class="toggleData ? 'style-one' : 'style-two'"> <!-- Check if toggledata true we use style-one css, if not style-two -->
<img :src="toggleData ? 'image-one-link' : 'image-link-two'" /> <!-- Check if toggledata true we use image-one-link, if not image-two-link -->
</div>
<div class="name" >Home</div>
</li>
</router-link>
<router-link to="/distination2">
<li>
<div class="Pic">
<img src='' />
</div>
<div class="Name">Home2</div>
</li>
</router-link>
<router-link to="/distination3">
<li>
<div class="Pic">
<img src='' />
</div>
<div class="Name">Home3</div>
</li>
</router-link>
<button #click="buttonClick"> Click Me </button> <!-- When button click we change toggleData value to true -->
</menu>
</template>
<script>
export default {
data() {
return {
toggleData: false,
};
},
methods: {
buttonClick() {
this.toggleData = true;
},
},
}
</script>
<style scoped>
.style-one {
background: red;
}
.style-two {
background: blue;
}
</style>
UPDATE:
I found an answer. Just added this little code at the bottom:
$('#myform').submit(function()
{
$('#dates option').prop('selected', true);
});
I have a tempate:
div class="panel">
<div class="large-12 columns">
<div class="row collapse">
<div class="small-10 columns">
<input class="input-append date fdatepicker" id="date" type="text" name="date" value="" data-date-format="dd/mm/yyyy">
</div>
<div class="small-2 columns">
<input type="button" name="add" id="btn_AddToList" value="dodaj" class="button postfix" />
</div>
</div>
</div>
<br>
<select multiple="multiple" size="10" style="height: auto; width: auto" name="dates" id="dates" tabindex="2">
</select>
</div>
and I add dates to #dates select using this little code:
$('#btn_AddToList').click(function () {
var val = $('#date').val();
$('#dates').append('<option value="'+val+'">' + val + '</option>');
$('#date').val('');
event.preventDefault();
event.stopPropagation();
})
in my view i want to read dates so i thought i would use:
for d in request.POST.getlist('dates'):
if d is not None:
print(d)
But I get None. I tried to use request.POST.getlist('dates[]'): request.POST.get('dates'): but with no success. I am recieving None all the time.
What I am doing wrong?
UPDATE: I found an answer. Just added this little code at the bottom:
$('#myform').submit(function()
{
$('#dates option').prop('selected', true);
});
In this example I want to use knockout.js to allow the "Expand" link to be clicked and have its text changed to "Collapse". I also want to set the make the jobDetails section visible. This is a very general question of how to get knockout.js to specifically modify the DOM of the "current" item in a list using a click handler.
<script type="text/html" id="job-template">
<div class="jobContainer">
<label data-bind="text: JobTitle"></label>
<label data-bind="text: CompanyName"></label>
<div class="jobDetails">
<label data-bind="text: City"></label>
<label data-bind="text: State"></label>
</di>
<div>
<a class="expand" href="#" data-bind="click: ???">Expand</a>
</div>
</div>
</script>
This is very straight forward with KO. Here's a simple way to do it. FYI I had to fix your markup slightly.
<div>
<div class="jobContainer">
<label data-bind="text: JobTitle"></label>
<label data-bind="text: CompanyName"></label>
<div class="jobDetails" data-bind="visible: expanded">
<label data-bind="text: City"></label>
<label data-bind="text: State"></label>
</div>
<div>
<a class="expand" href="#" data-bind="click: toggle, text: linkLabel">Expand</a>
</div>
var viewModel = function() {
this.JobTitle = ko.observable("some job");
this.CompanyName = ko.observable("some company");
this.City = ko.observable("some city");
this.State = ko.observable("some state");
this.someValue = ko.observable().extend({ defaultIfNull: "some default" });
this.expanded = ko.observable(false);
this.linkLabel = ko.computed(function () {
return this.expanded() ? "collapse" : "expand";
}, this);
this.toggle = function () {
this.expanded(!this.expanded());
};
};
http://jsfiddle.net/madcapnmckay/XAzW6/
Hope this helps.
I'm trying to combine two ebmer.js examples: Integrating with jQuery UI and the todos example from emberjs.com. I want to have a todo list that is sortable.
Everything went smooth until I got to a point where I wanted to serialize the sortable. For that to work, I need to be able to add an attribute to the sortable items.
this is the template:
{{#collection Todos.TodosListView}}
{{#view Todos.TodoView contentBinding="content" checkedBinding="content.isDone"}}
<label>{{content.title}}</label>
{{/view}}
{{/collection}}
Todos.TodosListView is a CollectionView, similar to the menu in the jQuery UI example. Todos.TodoView is a Checkbox.
This generates the following html:
<div class="ember-view todo-list ui-sortable" id="ember267">
<div class="ember-view" id="ember284">
<input type="checkbox" class="ember-view ember-checkbox todo" id="ember297">
<label>
<script type="text/x-placeholder" id="metamorph-1-start"></script>
something to do
<script type="text/x-placeholder" id="metamorph-1-end"></script>
</label>
</div>
</div>
What I need to be able to do is edit the <div> that wraps the <input>. Assuming the todo's id is 1, I want to add serial=todos_1. I tried to add didInsertElement to TodoView and add an attribute to the parent view, but I didn't have access to the content of the view (the todo itself).
Is this possible?
Thanks for your help.
EDIT:
I found a workaround - adding the ID to the DOM as a hidden element.
The updated template:
{{#collection Todos.TodosListView}}
{{#view Todos.TodoView contentBinding="content" checkedBinding="content.isDone" serial="content.serial"}}
<label>{{content.title}}</label>
<span style="display: none;" class="todo-id">{{content.id}}</span>
{{/view}}
{{/collection}}
Todos.TodoView.didInsertElement:
didInsertElement: function() {
var $div = this.get('parentView').$();
var id = $div.children('.todo-id').text();
$div.attr('serial', 'todos_' + id);
}
Generated html:
<div class="ember-view todo-list ui-sortable" id="ember267">
<div class="ember-view" id="ember284" serial="todos_100">
<input type="checkbox" class="ember-view ember-checkbox todo" id="ember297">
<label>
<script type="text/x-placeholder" id="metamorph-1-start"></script>
something to do
<script type="text/x-placeholder" id="metamorph-1-end"></script>
</label>
<span class="todo-id" style="display: none;">
<script type="text/x-placeholder" id="metamorph-2-start"></script>
100
<script type="text/x-placeholder" id="metamorph-2-end"></script>
</span>
</div>
</div>
I would still like to know if there's a more elegant way of achieving this.
You can create a computed property serial and add this property to the attributeBindings (documented here) of your itemViewClass of Todos.TodosListView, see http://jsfiddle.net/pangratz666/6X4QU/:
Todos.TodosListView = Ember.CollectionView.extend({
itemViewClass: Ember.View.extend({
attributeBindings: ['serial'],
serial: function() {
return 'todos_' + Ember.getPath(this, 'content.id');
}.property('content.id').cacheable()
})
});