Linking the movement of a DIV element to specific object properties using knockoutjs

I am currently working with an object that serves as a representation of the div element

function ElementVM
{
    var self = this;

    self.Height = ko.observable();
    self.Width = ko.observable();
    self.Bottom = ko.observable();
}

and I want to connect this object to

<div data-bind="style:{ height: Height, width: Width, bottom: Bottom, position: 'absolute' }">

However, my issue arises when dragging this div element which is set to be draggable as it does not update the values of my ElementVM object.

Have you encountered this problem before and do you have any insights on how the binding should be implemented?

Your assistance is greatly appreciated.

Answer №1

If you want to accomplish this task, custom bindings are the way to go. You can find an example below, or check it out on this jsfiddle.

// http://knockoutjs.com/documentation/custom-bindings.html
ko.bindingHandlers.draggable = {
     init : function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
        var $element = $(element);
        var position = ko.unwrap(valueAccessor());
        if (position) {
            if (position.left) 
                $element.css({left:ko.unwrap(position.left)});
            if (position.top) 
                $element.css({top:ko.unwrap(position.top)});
            if (position.height) 
                $element.height(ko.unwrap(position.height));
            if (position.width) 
                $element.width(ko.unwrap(position.width));
        }
        var draggable = $element.draggable({
            stop: function(event,ui) {
                if (position) {
                    if (ko.isWritableObservable(position.left))
                       position.left(ui.position.left);
                    if (ko.isWritableObservable(position.top))
                       position.top(ui.position.top);
                    if (ko.isWritableObservable(position.height))
                       position.height($element.height());
                    if (ko.isWritableObservable(position.width))
                       position.width($element.width());
                }
            }
        });
    },
    update : function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever any observables/computeds that are accessed change
        // Update the DOM element based on the supplied values here.
        var position = ko.unwrap(valueAccessor());
        var $element = $(element);
        if (position.left)
$element.css({left:ko.unwrap(position.left)+'px'});
        if (position.top)
$element.css({top:ko.unwrap(position.top)+'px'});
        if (position.height)
            $element.height(ko.unwrap(position.height));
        if (position.width)
            $element.width(ko.unwrap(position.width));
    }
};

var vm = {
    position: ko.observable({
    left: ko.observable(150),
    top: ko.observable(125),
    width: ko.observable(100),
    height: ko.observable(40)
    })
};

ko.applyBindings(vm);
div {
    border: solid 1px #444;
    background-color: #DDD;
    text-align: center;
    padding: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>  
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div data-bind="draggable: position"
     style="position:absolute;">
    This is a draggable div
</div>
<ul>
    <li>Top: <input type="textbox" data-bind="value: position().top"/></li>
    <li>Left: <input type="textbox" data-bind="value: position().left"/></li>
    <li>Width: <input type="textbox" data-bind="value: position().width"/></li>
    <li>Height: <input type="textbox" data-bind="value: position().height"/></li>
</ul>
<pre data-bind="text:JSON.stringify(ko.toJS($root),null,2)"></pre>

Answer №2

The knockout "style" binding operates in a one-way manner, detecting changes in the model and updating the corresponding view (such as an HTML element).

If you need to update model values based on changes in an HTML element, you must handle this through your own code. This could involve subscribing to window.resize events or periodically checking the size of the HTML element.

To achieve this functionality, consider using a custom binding or creating a component that handles the necessary interactions.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Passing predefined functions to asynchronous functions can be achieved by simply defining the

I am facing a challenge in passing a predefined function within an async function. The piece of code below is functioning flawlessly: async.auto({ getAccessToken: function (callback) { let x = { access_token: signToken({ userId: u ...

Using sinon.js version 1.10, jQuery version 2.1, and making synchronous requests

I have been attempting to simulate a server using sinon.js and calling it with jQuery.ajax, but I am facing issues getting it to work. Here is the code snippet: $(function() { var server = sinon.fakeServer.create(); server.respondWith('POST&apo ...

Using AJAX to send data with a POST request in Django may not function properly

Let me preface by saying I have searched for solutions online, but none of them seem to address my specific issue (mainly because they use outdated methods like Jason). I am currently working on a Django project and trying to implement ajax for a particul ...

Removing an item from an array in Mongoose

I'm encountering an issue with removing an Object from an Array and I'm unsure of the correct way to use $pull for this action. Any help would be greatly appreciated! JSON data "accountId": "62efd8c008f424af397b415d", "l ...

Step-by-step guide on generating a deb or exe file for an Angular Electron application

I am currently developing an Angular 6 project and I have a desire to turn it into a desktop application using Electron. After successfully installing Electron in my project, I encountered some challenges when trying to create builds for multiple platforms ...

JQuery and Fancybox causing issues when triggered on Internet Explorer 8

I am experiencing an issue with my jQuery code on my webpage. It works perfectly fine in Chrome, but I encounter an error in Internet Explorer 8 specifically in the trigger('click') line. $('#btnd16').click(function(e){ var iiid = ...

Unexpected changes are observed in the size of DIV elements when adjusting the SVG viewBox

My aim is to make the <svg> element have the same dimensions for the viewBox as the <div> it is inside. This means that the viewBox values need to match the dimensions of the containing <div>. Here is an example: <div style="width ...

Combining JavaScript functions and Vue.js methods through chaining

When working within a Vue component, I have a scenario where I am invoking a function from a separate JavaScript file. The requirement is to then trigger a method within my component once the first function has finished executing: Here is an example of my ...

Using the toggle method or IF statements in JavaScript to implement show and hide functionality upon clicking

I’ve been struggling with this issue for days now. It seems like I may have overcomplicated a simple piece of code. I'm trying to show some divs when a button is clicked, but I’m having trouble getting it to work properly. Initially, I used VAR.st ...

What advantages does using immutablejs offer compared to using object.freeze?

I've scoured the internet trying to find convincing reasons for using immutablejs instead of Object.freeze(), but I still haven't found a satisfactory answer! What are the advantages of working with non-native data structures in this library ove ...

Changing a particular field value within an array of objects in Angular 4

I have a scenario where I created a class called security: class security { public id:number; public name:string; } Next, I initialized an array of security objects: let s:security[]=[{id:1,name:'Alex'},{id:2,name:'John'},{id:3,nam ...

Tips for successfully submitting multiple forms to a controller

I'm working on a project that has multiple forms on the same page, and I need to pass them all to a controller in one go. How can I accomplish this? <script> function onSaveButtonClicked() { var form = $("#SaveForm").serialize(); var fo ...

Convert a JavaScript array into an HTML table sorted by time

I am looking to convert an array into an HTML table sorted by time, including a rank and calculating the time loss for the first place. Here is an example of the array: let array = [ ["McNulty Oscar", "USA", "108:45.1"], ["Johansson Anton", "SWE", "87 ...

Is it possible to "deactivate" a jQuery action?

While exploring GitHub, I stumbled upon a library called jTinder, which allows me to create cards that can be swiped left or right. To begin, I set up the #tinderslide div: <div id="tinderslide"><ul></ul></div> The cards are gener ...

Any suggestions on the most effective method for translating command-line arguments into JSON format?

I'm currently working on enhancing the grunt-closure-linter npm project to make it more usable for my workflow. However, I've hit a roadblock that I need help with: My goal is to find a way to pass options to the command line tool gjslint, which ...

Encountering a runtime error in React while making an async call on a NextJS 13 page

I am currently working on implementing async calls using the new app layout in NextJS 13. I have been referring to the latest documentation page. However, I have encountered an error that I can't seem to resolve. https://i.sstatic.net/CpNmu.png Belo ...

What is the purpose of using translateY(-50%) to vertically center an element that is positioned at top: 50%?

I've noticed that this code successfully aligns a div vertically within its parent element: .element { position: relative; top: 50%; transform: translateY(-50%); } My curiosity lies in the reasoning behind this. Initially, I thought that the p ...

Having trouble with managing state changes in a React application using Multiple Checkbox components from M

Trying to update the state of multiple checkboxes and then send a POST request. Visually, the checkboxes change, but the form data remains unchanged. Here is the code snippet: export default function AccountInformations(props) { // const { enqueueSnack ...

How can I disable scrolling for the :target selector?

Does anyone know of a method to stop scrolling for the :target selector? It seems that when a link is clicked, the scrolling experience isn't very smooth. ...

Rails: Pagination for Comments within a Micropost

Does anyone know if it's possible to paginate comments under a micropost so that all 50 comments don't appear at once when the comment button is clicked? I'd like to create a system similar to Facebook where only a certain number of comments ...