How can I convert a JavaScript DOM object to a jQuery object?
<tr onclick="changeStatus(this)">
function changeStatus(myObject) {
XXX.removeClass();
}
What should I write in place of XXX?
I know I can make a workaround using an id and an id selector, but it is not so elegant.
Is there any way to convert a js DOM object to a jQuery object or using the this keyword in jQuery?
var $this = $(myObject);
$this is a jQuery object. You can create jQuery objects from DOM elements.
<tr onclick="changeStatus(this)">
function changeStatus(myObject) {
$(myObject).removeClass();
}
I would like to recommend doing your event binding with jQuery as well:
<tr class="change-status">
$('.change-status').on('click', function () {
$(this).removeClass( ... );
});
This is nice because now all the JS code is in one place and can be updated (in my opinion) more easily. Note that the class I added to the <tr> element is not necessary if you want to bind to all <tr> elements in the DOM.
Simply wrap the pass the DOM object in as the first argument.
$(myObject).removeClass('foo');
Related
My component template have an img
<img src="img/loading.gif" :data-src="url" class="live-snapshot-img" :class="{lazy:true, 'lazy-loaded': false}">
When it rendered, I'll trigger out the lazy event. The class will changed to 'lazy-loaded' from 'lazy'.
<img src="img/loading.gif" :data-src="url" class="live-snapshot-img lazy-loaded">
Then if the data changed, I want the class change back to 'lazy'. The bind:class doesn't work.
My solution is
Create a method in component
lazyload: function() {
var clazz = {lazy: true, 'lazy-loaded': false}
clazz['dummy' + Math.random()] = true
return clazz
},
and change the img to
<img src="img/loading.gif" :data-src="url" class="live-snapshot-img" :class="lazyload()">
I think you're approaching this in slightly the wrong way. You have the right idea, but I feel like your thinking and jQuery post render dom manipulation manner, not that this is bad, just not right for this situation. Vue works a little differently. If you want to change the class after the event in this particular instance, you bind your :class to a variable in your vue component.
If I wanted to make this happen, I would probably start by setting a variables in my component data for the state. (see: Class and Style Bindings)
Vue.component('my-component-name', {
data: function () {
return {
imageState: {'lazy': true, 'lazy-loaded': false}
}
}
})
Then bind that to your element:
<img src="img/loading.gif" :data-src="url" class="live-snapshot-img" :class="imageState">
You can then manipulate the imageState in your component methods in any way you want.
I would like to create a dynamic form using polymer, meaning that everytime the user press "add" button,it will add a new field in the form. Or, more specifically, it will add a paper-dropdown-menu, where all of the options come from a dom-repeat fed by an ajax call.
this is what i've done so far:
<div id="filterContainer">
<div class="flex rulesForm" id="filter1">
<paper-dropdown-menu name="rule1A" no-label-float>
<paper-listbox attr-for-selected="value" selected="{{filter1A}}" class="dropdown-content" id="thirdPartyFilter1A">
<template is="dom-repeat" items="{{rule1A}}">
<paper-item value="[[item]]">[[item]]</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
</div>
</div>
<paper-button raised on-tap="addFilterField">Add</paper-button>
<div>
and in the JS:
addFilterField: function () {
let dropdown = document.createElement('paper-dropdown-menu');
dropdown.name = "";
dropdown.noLabelFloat = true;
let listbox = document.createElement('paper-listbox');
listbox.class = "dropdown-content";
listbox.attrForSelected = "value";
listbox.selected = "{{filter1A}}";
let paperItem = document.createElement('paper-item');
paperItem.value = "[[item]]";
var itemNode = document.createTextNode('[[item]]');
paperItem.appendChild(itemNode);
listbox.appendChild(paperItem);
dropdown.appendChild(listbox);
console.log(dropdown);
filterContainer.appendChild(dropdown);
my problem is about the data-binding... If I use createTextNode with [[item]], it will simply write it as a string in the document. Is there a way to fix this? (or a way easier solution to add field in a form?)
first of all you cannot use binding notation in javascript. it is markup
2nd, polymer doesn't yet support creating data bindings dynamically. however I'm sure you can accomplish what you are trying to do.
3rd,
you have to use the Polymer Dom API. https://www.polymer-project.org/1.0/docs/devguide/local-dom#dom-api
instead of paperItem.appendChild(itemNode)
you would use
Polymer.dom(listbox).appendChild(itemNode);
Here is my code:
function MainCtrl($scope) {
$scope.thisarray = globalObj;
$scope.loadthis = function (index) {
return thisarray[index];
}
}
Here is the markup:
<table ng-controller="MainCtrl">
<tr>
<td ng-repeat="element in thisarray">
{{loadthis($index)}}
</td>
</tr>
</table>
I'm loading some data through a SOAP callback:
SOAPCLient.invoke(url, methodName, pl, true, function(obj) {globalObj = obj;
**angular.bootstrap("html");**//here is where I try to reinitialize the app
});
If you look at the SOAP call, I use bootstrap to reinitialize the app, but it has not been working. loadthis does not display any data inside the HTML table. Can anyone help me here?
You could listen for changes to the SOAP using $.watch and then $.apply when trying to force a push. See examples of how to use here
You should not be re-initializing AngularJS application every time you've got data arriving from an external source. Instead of destroying and re-creating AngularJS the way to go would be to use $apply method on a scope object.
The pseudo-code (in your controller) would be like:
SOAPCLient.invoke(url, methodName, pl, true, function(obj) {
$scope.apply(function(){
$scope.thisarray = obj;
});
});
Also, if I understand your code correctly you would invoke a SOAP call for each item in a repeater (ng-repeat) while your SOAP call is bringing back data for all objects. So the better approach would be to do a SOAP call (as in a snippet above), assign data to a variable in a scope and let the ngRepeat do its magic.
I might be misunderstanding what you are trying to achieve here so having a jsFiddle / plunker with your code would help to provide more detailed response.
I have a menu that I want to differ based on which account is currently selected in the system.
I have a page that allows a user to select an account from an html select. When the user submits the form from the account selection page I want to call the menu method on my controller passing in the selected value so my url looks correct.
Here is the existing template from the page that allows a user to select an account:
#helper.form(action = routes.Accounts.menu {
<table>
<tr>
<td><select id="accountNames">
#accountNames.map { name =>
<option value="#name">#name</option>
}
</select></td>
</tr>
<tr>
<td>
<p>
<input type="submit" value="Choose">
</p>
</td>
</tr>
</table>
}
From my routes file:
GET /account/:accountName/menu controllers.Accounts.menu(accountName: String)
How do I reference the selected value from my select (id="accountNames") and pass it into my form action?
Actually I think you're on the wrong side for doing that.
If the form's action has to change over the use of your 'select', it has to be done using JS.
So when the form is submitted (event submit) you have to update the url.
This can be done easily using javascriptRoutes.
So you have to do several things:
1/ create the javascriptRouter (assuming your add it in Application.scala)
def javascriptRoutes = Action {
Ok(
Routes.javascriptRouter("playRoutes")(
//accounts
controllers.routes.javascript.Accounts.menu
)
).as("text/javascript")
}
2/ define it in your routes file
# Javascript routing
GET /assets/javascripts/routes controllers.Application.javascriptRoutes
3/ add the related javascript file import in your views, let say in main.scala.html
<script type="text/javascript" src="#routes.Application.javascriptRoutes"></script>
4/ add a submit handler to your form that does that before executing the default behavior
$("form").submit(function () {
//this computes the correct URL giving a parameter which is the value of the selected option
var newURl = playRoutes.controllers.Accounts.menu($("#accountNames").val()).url
$(this).attr("action", newUrl);
})
Notice how we've used playRoutes both in the controller (1) and the JS call (4).
Hi I have the following scenario.
Some elements are nested within a with
<!-- ko with: model.selected_item -->
<tr>
<td style="width:20%">Name:</td>
<td style="width:80%" class="field" data-bind="text: name"></td>
<td style="width:10px"><div class="btn_edit"></div></td>
</tr>
<tr>
etc...
<!-- /ko -->
$("div.btn_edit", component.context).on("vclick", function(e){
//edit it
}
The problem I have is that if the selected_item changes - I loose the bindings on the edit button.
In this scenario, it is a little difficult to subscribe to the model.selected_item and reapply the bindings - so I'd like to get notified when the elements within the with directive are updated and reapply then.
Is there a knockout specific way to achieve this?
An help much appreciated.
The reason you are getting this problem is that the click handler element is being destroyed by the template engine each time you update item.
Here is an example of the way to achieve what you want without resorting to jquery delegate bindings, which while they do work they are poluting your otherwise nice KO model with needless dom operations. Everytime I find myself using the old $() selector with a KO app I have to seriously consider whether there is a better model oriented way.
http://jsfiddle.net/madcapnmckay/EFQ9S/
The gist of this is to convert your model into true js classes and use those to bind KO click events rather than jquery click handlers. The beauty of this approach is that KO will rebind for you elements when they get destroyed.
var item = function (config) {
var self = this;
this.name = ko.observable(config.name);
this.edit = function () {
$("body").append("<div>lets edit " + self.name()+"</div>");
};
};
var model = function() {
this.item = ko.observable();
this.pushNew = function () {
this.item(new item({name: "new name"}));
};
}
$(document).ready(function(e) {
var mymodel = new model();
ko.applyBindings(mymodel);
mymodel.item(new item({ name: "the_name" }));
})
Hope this helps.