How to add a Dojo Button in Div dynamically by using Dojo? - dojo

I have a the following static div:
<body>
<div id="parent">
</div>
</body>
<script>
dom.byId('parent').innerHTML +="<input type='submit' data-dojo-type='dijit/form/Button' onClick='test(this)' id='edit"+1+"' label='Edit' />";
dom.byId('parent').innerHTML +="<input type='submit' data-dojo-type='dijit/form/Button' onClick='test(this)' id='edit"+2+"' label='Edit' />";
</script>
TWo button's are created but they looks like normal HTML not DOJO.

The shortest possible answer is dojo/parser::parse(domNode):
var parent1 = dom.byId("parent1");
parent1.innerHTML += '<input type="submit" data-dojo-type="dijit/form/Button" onClick="test(this)" id="edit1" label="Edit 1">';
parent1.innerHTML += '<input type="submit" data-dojo-type="dijit/form/Button" onClick="test(this)" id="edit2" label="Edit 2">';
parser.parse(parent1);
Even though I cannot recommend that. Do not use innerHTML, it belongs to the world of IE6. Create dijits programmatically instead:
var parent2 = dom.byId("parent2");
var button3 = new Button({ label: "Button 3" });
button3.startup();
button3.placeAt(parent2);
button3.on("click", test);
var button4 = new Button({ label:"Button 4"});
button4.startup();
button4.placeAt(parent2);
button4.on("click", function(event) {
test(this); // `this` points to the button
});
See it in action: http://jsfiddle.net/phusick/9JCAj/

Related

How to bind change on text area to v-model value?

I have this checkbox that will generate raw HTML on textarea, then generate whatever contain in textarea to the picture on top of the form, on that textarea, I want to be able to edit the text to customize the data position on the image.
The checkbox and the pic work fine, but when I edit data on the textarea, it reverts back, and of course, the rendered HTML reverts back too. And 1 more thing, I have to open the vue extension on inspecting menu to get all DOM rendered
Pic render code
<template>
<div class="card-item container-fluid mt--7">
<div class="card-item__cover">
<img v-if="form.img" :src="background" class="imageBackground" />
<div
v-if="previewImage"
class="imageBackground"
:style="{ 'background-image': `url(${previewImage})` }"
></div>
</div>
<span v-html="htmlBaru"></span>
</div>
</template>
Textarea
<div class="form-group">
<label class="col-form-label form-control-label">HTML</label>
<textarea
ref="htmlInput"
rows="4"
class="form-control col-sm-10"
v-model="htmlBaru"
#change="pantek"
></textarea>
</div>
Checkbox
checkboxCond() {
var sendKeyData = [];
var newHtml = [];
for (var a = 0; a < this.keyData.length; a++) {
if (this.keyData[a].status) {
newHtml.push(
`<tr>
<td >` +
this.keyData[a].key_readable +
` : {` +
this.keyData[a].key +
`}</td>
</tr>`
);
sendKeyData.push(this.keyData[a].key);
}
}
this.htmlBaru = this.html + newHtml.join("\r\n") + this.footer;
this.sendKeyData = sendKeyData;
console.log(this.htmlBaru);
// return this.htmlBaru;
}
Onchange
methods: {
pantek() {
// console.log(this.htmlBaru);
this.htmlBaru = this.$refs.target.value;
// this.$emit("change", this.htmlBaru);
},
}

vue.js - Add a placeholder in text box with click of a button

I have a textbox
<div>
<b-form-textarea
id="textarea"
v-model="text"
placeholder="Certification text "
rows="5"
max-rows="6"
></b-form-textarea>
</div>
And two buttons
<b-button variant="primary" class="btn btn-primary btn-lg top-right-button mr-1">Save</b-button>
<b-button variant="info" class="btn btn-info btn-lg top-right-button mr-1">Add Name</b-button>
When the user is typing and in between if he clicks Add Name button {name} should be placed in the textbox (Where ever the cursor is).
How can i implement it?
You can add a ref to your textarea, and access the selectionStart property, which contains the placement of the cursor.
You can then use this index to splice the given text into the textarea's text at the given position.
And since clicking the button will lose the focus of the input, you can add it back by calling the focus method on the ref, along with setting the selectionStart and selectionEnd so the cursor is where it left off.
new Vue({
el: "#app",
data() {
return {
text: ""
};
},
methods: {
addName() {
const { text } = this;
const textarea = this.$refs["my-textarea"].$el;
const index = textarea.selectionStart;
const name = "{name}";
this.text = `${text.substring(0, index)}${name}${text.substring(
index
)}`;
textarea.focus();
setTimeout(() => {
textarea.selectionStart = index + name.length;
textarea.selectionEnd = index + name.length;
});
}
}
});
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.17.3/dist/bootstrap-vue.js"></script>
<link href="https://unpkg.com/bootstrap#4.5.2/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.17.3/dist/bootstrap-vue.css" rel="stylesheet" />
<div id="app">
<b-form-textarea ref="my-textarea" v-model="text" placeholder="Certification text" rows="5" max-rows="6">
</b-form-textarea>
<b-btn variant="primary" size="lg" #click="addName">
Add Name
</b-btn>
</div>

Binding vue components to class name

Alright so I am trying to bind this vue components to a class name so it triggers on every element that has this class but what happens is that it only works with the first element and not with other ones
<div class="__comment_post">
<textarea></textarea>
<input type="submit" v-on:click="submitComment" /> <!-- submit comment being only triggered on this one -->
</div>
<div class="__comment_post">
<textarea></textarea>
<input type="submit" v-on:click="submitComment" />
</div>
<div class="__comment_post">
<textarea></textarea>
<input type="submit" v-on:click="submitComment" />
</div>
As you can see above, I've got 3 divs with class __comment_post so naturally submitComment should be bound to all these 3 divs but what happens is that submitComment is being triggered only on the first one
var app = new Vue({
el:".__comment_post",
data: {
comment: ""
},
methods: {
submitComment: function() {
console.log("Test");
}
}
});
Here is a little example you and others can follow in order to bind vue instance to class names.
Lets say, you would like to bind Vue to multiple existing <div class="comment"> element in HTML.
HTML:
<div class="comment" data-id="1">
<div>
<div class="comment" data-id="2">
<div>
Now, you can try the following logic/code to your example.
JS:
var comments = {
"1": {"content": "Comment 1"},
"2": {"content": "Comment 2"}
}
$('.comment').each(function () {
var $el = $(this)
var id = $el.attr('data-id')
var data = comments[id]
new Vue({
el: this,
data: data,
template: '<div class="comment">{{ content }}<div>'
})
})
I hope this will answer your question :)
The vue instance is mounted on the first found DOM element with the css selector passed to the el option. So the rest two div have no vue instances mounted on them.
So wrap your divs with a wrapper div and mount the vue instance on that wrapper
<div id="app">
<div class="__comment_post">
<textarea></textarea>
<input type="submit" v-on:click="submitComment" /> <!-- submit comment being only triggered on this one -->
</div>
<div class="__comment_post">
<textarea></textarea>
<input type="submit" v-on:click="submitComment" />
</div>
<div class="__comment_post">
<textarea></textarea>
<input type="submit" v-on:click="submitComment" />
</div>
script
var app = new Vue({
el:"#app",
data: {
comment: ""
},
methods: {
submitComment: function() {
console.log("Test");
}
}
});

Empty TabContainer in Dojo Dialog

The problem is that the TabConainer inside the Dialog is empty after opening although selected="true" is given (see the screenshot below). The content is called with dojo/html html.set(node, contentHTML, {parseContent: true});
When changing the tab by clicking on another one the content appears and the class "dijitVisible" is set for this div as it should be from the beginning. The attribute nested="true" is necessary since otherwise three select bars are shown over the tabContainer.
What can I do so that the content appears from the start on?
<div data-dojo-type="dijit/Dialog" id="formDialog" data-dojo-id="formDialog" title="Edit member data">
<div id="formContent" class="dijitDialogPaneContentArea" data-dojo-attach-point="formContent">
</div>
</div>
Update:
Here is the whole javascript for getting the content
getForm = function(formID, urlAction){
var contentHTML;
var xhrArgs = {
url: urlAction,
handleAs: "text",
load: function(data){
contentHTML = data;
},
error: function(error){
contentHTML = text_error_unexpected + ": " + error;
},
handle: function(error, ioargs){
var node = dom.byId(formID);
html.set(node, contentHTML, {parseContent: true});
}
}
var deferred = dojo.xhrGet(xhrArgs);
};
Update 2:
This is the content that gets called and inserted in the above div "formContent" (I thought I make the description as simple as possible and lost some details on the way)
<div id="form" data-dojo-type="dijit/form/Form" data-dojo-attach-point="form" encType="multipart/form-data" action="#">
<div style="width: 450px; height: 370px;">
<div data-dojo-type="dijit/layout/TabContainer" nested="true">
<div data-dojo-type="dijit/layout/ContentPane" title="Personal data" selected="true">
Content 1
</div>
<div data-dojo-type="dijit/layout/ContentPane" title="Detailed data">
Content 2
</div>
<div data-dojo-type="dijit/layout/ContentPane" title="Contact data">
Content 3
</div>
</div>
</div>
</div>
Have you tried calling either dialog.resize() or tabcontainer.layout() after adding it to the dialog?
I am not sure as to how the code below will place contents inside the first ContentPane (title="Personal data"). I am assuming that the parameter formID = "form"
html.set(node, contentHTML, {parseContent: true});
I can suggest an alterantive.
Use an id with the content pane as shown below.
<div id="content1" data-dojo-type="dijit/layout/ContentPane" title="Personal data" selected="true">
Content 1
</div>
Then use dijit/registry to get the contentpane widget in the handle function call as shown below.
handle: function(error, ioargs){
var content= registry.bId(formId); // over here formId = "content1"
content.set("content","<p>This is content for <b>Personal Data</b></p>");
//content.set("content", contentHTML);
}
EDIT 1
This is may be one possible solution.
#Richard had suggested dialog.resize(), which I did try to put it after the html.set code but it would not work.
What I have noticed is that the html.set takes some time to execute and the dialog.resize() does not work because it is
called before the completion of the html.set call.
html.set also complicates the issue as it does not provide any handle (promise object) to let us know when it has finished execution.
so the below solution uses a setTimeout call to delay the execution of the dialog.resize(). Hence would advice to put the value of delay time depending upon some actual UI testing.
Modified code.
handle: function(error, ioargs){
var node = dom.byId(formID);
html.set(node, contentHTML, {parseContent: true});
var dialog = registry.bId("formDialog");
setTimeout( function(){
dialog.show();
dialog.resize();
},2000) // time delay of 2 seconds
}

Dojo - dijit.dialog

Here's the flow of my problem:
I have one modal dialog, when I open a new dialog, it would open contentOne.jsp inside the modal dialog. When I click on a link on contentOne.jsp, the modal dialog refreshes and open contentTwo.jsp with my href reference. Then I close the dialog. When I open the dialog again, it would open contentTwo.jsp not contentOne.jsp. I tried destroyDescendants, destroyRendering.... but they didn't work.
I have a header that has a link to open a modal dialog like the following:
<div style="position: relative;right: 50px; top: 15px;">
<a onclick="dijit.byId('selectEquipmentInfo').show(); return false;" href="" />Add Equipment</a>
</div>
<%-- start equipment info dialog link --%>
<div id="selectEquipmentInfo" style="display:none;" name="selectEquipmentInfo" dojotype="dijit.Dialog" draggable="false" title="Select Equipment">
<div style="width:870px; height:400px; padding: 10px; overflow-y:auto;" href="">
<%# include file="../../StoreInfoArea/ProductFamilyDisplay.jspf"%>
</div>
</div>
This should open a modal dialog. Inside my ProductFamilyDisplay.jspf, I have an item linked to another jsp page on 'href' like the following
<div id="productFamily" class="productFamilyContainer">
<div id= "prdctFamilyRow" class="productFamilyColumn">
<c:forEach var="equipmentInfo" items="${equipmentTestList}" varStatus="status">
<c:out value="${equipmentInfo.value}" /><br />
</c:forEach>
</div>
This will render on the same modal dialog, and it's being controlled by this javascript:
<script type="text/javascript">
dojo.addOnLoad (function(event){
dojo.connect(dijit.byId('selectEquipmentInfo'), 'onClick', clicked);
});
var clicked=function(event) {
var dialog=dijit.byId('selectEquipmentInfo');
var contentNode=dialog.domNode;
var node = event.target;
var attrId = dojo.attr(node, "id");
if (attrId =="dijitCloseLink" || attrId == "dijitCloseImg") {
dialog.set('href','');
} else {
if("a" == node.nodeName.toLowerCase()){
dialog.href=node.href;
dialog.refresh();
dojo.stopEvent(event);
}
}
};
</script>
I am not able to locate code to destroy the Dialog. Try given below code. Put this code in the div where you are creating the dialog.
dojo.connect(selectEquipmentInfo, "hide", function(e){
dijit.byId("selectEquipmentInfo").destroy();
});