Html.TextBoxFor not rendering when added by a library - javascript

I'm currently working on a website at work. Everything's been working so far, except when I've moved a function to a library so it can be reusable.
The function is a click event for a set of two radio buttons. When the "Yes" button is clicked, a textbox and it's label need to appear. When the "No" button is clicked, they need to disappear.
The label is appearing just fine on the "Yes" click. And the function as a whole worked perfectly on the page itself. However, when I moved the script to a library for reusability within the project, the textbox no longer appears. I have tried swapping out for an input tag, with similar results.
The relevant html:
#ModelType PROJECT.Form
#Code
ViewData("Title") = "PageTitle"
Layout = "~/Views/Shared/_LayoutPage.Desktop.vbhtml"
End Code
<script>
$(function () { initFunction() })
</script>
#Using Html.BeginForm("Process", "Home")
#Html.AntiForgeryToken()
#Html.Hidden("page", 4)
#<div id="formColumn" class="grid_19 alpha">
<h3>Process Title</h3>
<fieldset>
<legend>Page Title</legend>
<ol class="grid_18 push_1">
//a couple yes/no questions here, works fine
<li><label>Question 3</label></li>
<li>
<ol id="appendHere"class="horizontalList clearfix">
<li><label>Yes</label></li>
<li>#Html.RadioButtonFor(Function(a) a.Q3Radio, True)</li>
<li><label>No</label></li>
<li>#Html.RadioButtonFor(Function(a) a.Q3Radio, False)</li>
</ol>
</li>
//more working stuff
</ol>
<div class="clear"></div>
<button name="submit" id="submit" value="submit" class="push_1">Submit</button>
<button name="cancel" id="cancel" value="cancel" class="push_1">Cancel</button>
<button name="back" id="back" value="back" class="push_1">Back</button>
</fieldset>
</div>
End Using
The javascript:
function initFunction() {
$(function () { $("input[name=Q3Radio]").click(function () { handleQ3Check(this) }) })
var check = true
function handleQ3Check(elem) {
if (elem.value == "True") {
if (check) {
$('#appendHere').append('<li class="appended"><label>Amount: $</label></li><li class="appended">#Html.TextBoxFor(Function(a) a.appendAmount)</li>')
$(function () { $("input[name=appendAmount]").blur(function () { handleFees(this, 'stuff') }) })
check = false
}
} else {
var appendedInput = $('.appended')
if (appendedInput != null) {
handleFees(appendedInput, 'stuff')
$(appendedInput).remove()
check = true
}
}
}
}
As stated above, I have tried making the textbox out of an input tag, but that does not appear. What appears with this case is Amount: $ #Html.TextboxFor(Function(a) a.appendAmount) exactly like that.
Any help or nudges in the right direction while I further attempt to debug the issue would be greatly appreciated.

When you include the Javascript in the same vbhtml file the reason why it works is that the vbhtml file gets compiled before it is then sent out to the client's browser. Have a look at the javascript that is getting rendered either by viewing the source or using developer tools/or similar in your favourite browser.
When you ask javascript to write out
$('#appendHere').append('<li class="appended"><label>Amount: $</label></li>
<li class="appended">#Html.TextBoxFor(Function(a) a.appendAmount)</li>')
It will do just that.
Judging by your comments it seems as though you're already aware of this though :-) and that you're making progress.

Related

Reload Data with .sort from Dynamic Table with Jquery | JSON | Sort with New Data

I have been trying for a few days that when I use the .sort property the data is eliminated or modified instead of it being reloaded as new lines.
Attach Captures from the code Working
Image1 How work the code when i press the button, this sort to the highest price to lowest but how do you can see in the second image, the code appears up and this not delete the old data
Marked with "X" the data that does not have to show
this fragment is the one that generates the tables dynamically
const mostrarProductos = () => {
$.getJSON(URLJSON, (respuesta) => {
for (let z of respuesta) {
productosv2.push(z);
}
for (let x of productosv2) {
$("#fila").append(`
<tr class="deleteProductos">
<div class="card text-center" style="width: 18rem;" id='btnBorrarCarrito'>
<div class="card-body">
<input type="hidden" id="idProd" value="${x.id}"> </td>
<td class="card-title" id="${x.id}">${x.producto}</h2> </td>
<td class="card-text">$ ${x.precio}</p></td>
<div class="btn-group" role="group" aria-label="Basic mixed styles example">
<td><button type="button" class="btn btn-success" onclick="agregarCarrito(${x.id})">Agregar</button></td>
</div>
</div>
</div>
</tr>
`);
}
$("#fila").fadeIn("5000");
});
};
And this function is what orders them
function respuestaClickExpensive() {
$("#fila").html('');
let productosordenados = productosv2.sort((a, b) => {
if (a.precio > b.precio) {
return -1;
}
if (a.precio < b.precio) {
return 1;
}
return 0;
});
return productosordenados;
}
The one that orders them from smallest to largest is the same only that different signs and names.
As you can see I tried to use a ".html ("")" since previously in another cart attempt it used .innerHtml (Which does not work in this case either, Also the code of the cart is totally different from that moment that it worked for me
)
I tried the following:
$ ("#fila"). empty ();
Make another function to clean with .empty
Use Native JavaScript to generate the code.
$ ("#fila"). remove (); this removes all the content for me but does not regenerate it.
Change the HTML tag "Row" to a previous div which, since the div was not generated again, did not generate it again.
$ ("#fila tr"). remove ();
And some more things that I don't remember right now.
If you can guide me on what I did wrong or any suggestions to fix it, I appreciate it.
If I had to follow a template about posting on StackOverFlow or having chosen or named in a different way, I appreciate your comment since it is my first post
Project notes of possible relevance: The complete code outside of html and css is made with Native JavaScript, Jquery, Ajax, SASS and BootStrap.

rateYo jquery plugin function star rating codeigniter/php

HTML:
<div id="submit-review">
<form action="<?=base_url()?>story/submit_review/<?=$story['story_id']?>" method="post">
<div class="form-group">
<label for="review-rating">Rate the story</label>
<div id="review-rating"></div>
</div>
<div class="form-group">
<label for="review-content">Write your review</label>
<textarea class="form-control" name="review-content"></textarea>
</div>
<button class="btn btn-default">Post Review</button>
</form>
</div>
<script>
$(function () {
tinymce.init({
selector:'textarea'
});
$("#review-rating").rateYo({
starWidth:"25px"
});
});
</script>
Controller:
public function submit_review(){
$story_id = $this->uri->segment(3);
$review_content = $this->input->post('review-content');
}
I tried experimenting with the jquery script provided by the website:
$(function () {
var $rateYo = $("#rateYo").rateYo();
$("#getRating").click(function () {
/* get rating */
var rating = $rateYo.rateYo("rating");
window.alert("Its " + rating + " Yo!");
});
$("#setRating").click(function () {
/* set rating */
var rating = getRandomRating();
$rateYo.rateYo("rating", rating);
});
});
But i keep having problems, I don't have any background in jquery. I've done javascript validation but that was years ago. I could relearn but then i'd have to start with javascript first.
My idea is to somehow set a value to a hidden input type inside my <form> then just get it from there via post in CI.
<input id='review-rating' type="hidden" value=""></input>
var $rateYo = $("#review-rating").rateYo();
$("#submit-review").click(function () {
var rating = $rateYo.rateYo("review-rating");
$("#hidden-rating").val(rating);
window.alert("Its " + rating + " Yo!");
});
But i could not test the above code if it works or not because whenever i try to add it, my other jquery functions won't work. I'm using rateYo plugin and tinymce.
This is my current scripts:
$(function () {
tinymce.init({
selector:'textarea'
});
$("#story-rating").rateYo({
rating: <?=$story['rating']?>,
readOnly: true
});
<?php if(isset($reviews['your_review']) AND $reviews['your_review'] != NULL){ ?>
$("#my-rating").rateYo({
rating: <?=$your_review_rating?>,
readOnly: true,
starWidth: "25px"
});
<?php } ?>
$("#review-rating").rateYo({
starWidth:"25px"
});
<?php foreach($reviews['other_reviews'] as $id=>$row){ ?>
$("#rating-<?=$id?>").rateYo({
rating: <?=$row['rating']?>,
readOnly: true,
starWidth: "25px"
});
<?php } ?>
});
I barely got the above to work.
Anyway, my question is, how do i pass the rateYo value to my CI controller? if my above idea is of sound logic, then can you write how the syntax should look like here?
I guess i'm learning jquery as i need them, albeit messy.(i can't concentrate reading wall of texts/codes, i learn better by trying them)
Okay so while i was waiting for any answer. I read a quick tutorial on W3school.(i find w3school a reliable source for tutorials on anything, any other tutorials are either too complex or assumes the reader knows everything there is to know that leaves them confused)
So i changed the code abit:
var rating = $("#review-rating").rateYo("rating");
$("#hidden-rating").val(rating);
I've attached the above code to a button click event.
Now i can finally get the value from the controller:
$this->input->post('hidden-rating');
Still i'll wait for even better answers.

Salesforce Lightning Component will not update records via Apex call, freezes

Issue overview: Currently coding a Lightning Component to update records on a custom object. However, every time I trigger the update (via a ui:button), the page freezes and I don't see any errors in the debugger or console. Cannot for the life of me figure out why it won't work.
Context: The component has a number of dropdowns that are populated with records (with the label being the record name). Selecting a new value in the dropdown and hitting "Update" calls the below apex to change a custom field (Status__c = 'Ready') on the new selected item, and then updates the records that occur before it (Status__c = 'Complete). I do all of my security and update checks in another function during init, so you won't see that here (I can post the full code if needed). Just trying to get the update to work.
I would be eternally grateful if someone could show me the error of my ways :]. Always been a huge fan of stackoverflow and looking forward to contributing now that I finally signed up. Thanks for your time everyone!
Apex:
#AuraEnabled
public static void updateMilestones(String deployId,Boolean prodChanged,String newProdMile) {
if( prodChanged == true && newProdMile != null ) {
try {
decimal newProdStepNum;
List <Milestone__c> newReadyProdMile = New List<Milestone__c>();
for(Milestone__c mil1:[SELECT id, Status__c, Step_Order__c FROM Milestone__c
WHERE Deployment__c = :deployID
AND id = :newProdMile LIMIT 1]){
mil1.Status__c = 'Ready';
newProdStepNum = mil1.Step_Order__c;
newReadyProdMile.add(mil1);
}
List <Milestone__c> prodMilesComplete = New List<Milestone__c>();
for(Milestone__c mil2:[SELECT id, Type__C, Status__c FROM Milestone__c
WHERE Deployment__c = :deployID
AND Step_Order__c < :newProdStepNum
AND Type__c = 'Production'
AND Status__c != 'Complete'
AND Status__c != 'Revised']){
mil2.Status__c = 'Complete';
prodMilesComplete.add(mil2);
}
update newReadyProdMile;
update prodMilesComplete;
}
catch (DmlException e) {
throw new AuraHandledException('Sorry, the update did not work this time. Refresh and try again please!');
}
}
}
Javascript:
updateMilestones : function(component, event, helper) {
// update milestones server-side
var action = component.get("c.updateMilestones");
action.setParams({
deployId : component.get("v.recordId"),
newProdMile : component.find("prod-mile-select").get("v.value"),
prodChanged : component.get("v.prodChanged")
});
// Add callback behavior for when response is received
action.setCallback(this, function(response) {
var state = response.getState();
if (component.isValid() && state === "SUCCESS") {
// re-run the init function to refresh the data in the component
helper.milesInit(component);
// refresh record detail
$A.get("e.force:refreshView").fire();
// set Update Changed Milestones button back to disabled
component.find("updateButton").set("v.disabled","true");
// show success notification
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
"title": "Success!",
"message": "Milestones have been updated successfully."
});
toastEvent.fire();
}
});
// Send action off to be executed
$A.enqueueAction(action);
}
Component:
<aura:component controller="auraMilestonesController_v2"
implements="force:appHostable,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction">
<ltng:require scripts="{!$Resource.lodash}" afterScriptsLoaded="{!c.doInit}"/>
<aura:attribute name="recordId" type="String" />
<aura:attribute name="prodMiles" type="Milestone__c[]"/>
<aura:attribute name="prodChanged" type="Boolean" default="false"/>
<!-- FORM -->
<div class="slds-col slds-col--padded slds-p-top--large" id="theform">
<form class="slds-form--stacked">
<!-- UPDATE BUTTON -->
<div class="slds-form-element">
<ui:button aura:id="updateButton" label="Update Changed Milestones" press="{!c.updateMilestones}"
class="slds-button slds-button--brand slds-align--absolute-center" disabled="true"/>
</div>
<hr style="color: #005fb2;background-color: #005fb2;"/>
<!-- PRODUCTION -->
<div aura:id="prod-section">
<div class="slds-form-element">
<label class="slds-form-element__label" for="milestone">Production Milestone</label>
<div class="slds-form-element__control">
<div class="slds-select_container">
<ui:inputSelect aura:id="prod-mile-select" class="slds-select" change="{!c.prodChange}">
<option value="" >--Select One--</option>
<aura:iteration items="{!v.prodMiles}" var="m">
<aura:if isTrue="{!m.Status__c == 'Ready'}">
<option value="{!m.id}" selected="true">{!m.Name} ({!m.User_Name__c})</option>
</aura:if>
<aura:if isTrue="{!m.Status__c == 'Not Ready'}">
<option value="{!m.id}">{!m.Name} ({!m.User_Name__c})</option>
</aura:if>
</aura:iteration>
<option value="completeProdMile" id="completeProdMile">All Production Milestones Complete</option>
</ui:inputSelect>
</div>
</div>
</div>
<div class="slds-form-element">
<label class="slds-form-element__label" for="description">Description</label>
<div class="slds-textarea">
<aura:iteration items="{!v.prodMiles}" var="m">
<aura:if isTrue="{!m.Status__c == 'Ready'}">{!m.Description__c}</aura:if>
<!-- <aura:set attribute="else">All production milestones have been completed.</aura:set> -->
</aura:iteration>
</div>
<hr style="color: #005fb2;background-color: #005fb2;"/>
</div>
</div>
<!-- END PRODUCTION -->
</form>
</div>
<!-- / FORM -->
</aura:component>
I believe the issue is that you have fallen into the all too common trap of naming both a client side and a server side controller method the same (updateMilestones in this case). Try changing the name of either to make them unique and I expect that will get you running.
Yes, there is a bug on this and many of us have been making a very loud noise about getting it fixed!
Also we have a very active Salesforce specific Stack Exchange forum over here https://salesforce.stackexchange.com/ that will get more attention - especially if you tag your posts with lightning-components (e.g. I have my account configured to send me an email alert on every post tagged with lightning-components, locker-service, etc).
That might be javascript causing the error.As it's difficult to solve without knowing the error, I would suggest you debug the error.
Turn on debug mode.
a. From Setup, click Develop > Lightning Components.
b. Select the Enable Debug Mode checkbox.
c. Click Save.
In Chrome Developer Tools, check the "Pause on Caught Exceptions" checkbox in the Sources tab. This can often help finding the source of an issue. Other browsers may have similar options.
Add a debugger statement if you want to step through some code.
debugger;
This is useful when you have a rough idea where the problem might be happening.
debugger
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/debug_intro.htm

JavaScript function call on JQuery .load() doesn't behave like expected

I am working on a website for school, and am currently implement some sort of admin dashboard. For that, I decided to dynamically load 'modules' (actually simply .php files) into a div designed to hold them.
This works fine for modules that don't depend on specific js files, but there's one that needs the 'participation.js' file.
I had tested the module in a whole window where there was an 'onload="initSelectable()"' on the body directive, but calling this function when the module is loaded in the admin dashboard doesn't do anything.
Here is the content of participation.js (it is simply copy/pasted from the JQuery selectable, and I slightly modified the behaviour):
var selectedPlayerIDs = [];
function initSelectable(){
$('#selectable').selectable();
$('#submitParticipationBtn').hide();
console.log("initSelectable");
$("#selectable").selectable({
stop: function() {
var count = 8;
var result = $("#selectedPlayersCount").empty();
$(".ui-selected", this).each(function() {
count--;
selectedPlayerIDs.push($(this).attr("data-playerid"));
});
if(count > 1)
$('#selectedPlayersCount').html(count + " more players");
else if(count === 1)
$('#selectedPlayersCount').html(count + " more player");
else if(count === 0)
$('#selectedPlayersCount').html("no more player. You're good to go !");
else if(count === -1)
$('#selectedPlayersCount').html(-count + " player less");
else
$('#selectedPlayersCount').html(-count + " players less");
if(count === 0)
$('#submitParticipationBtn').show();
else
$('#submitParticipationBtn').hide();
}
});
}
function submitParticipation(){
alert( "JS loaded" );
$.post("participation.php", {selectedIDs : JSON.stringify(selectedPlayerIDs)}, function() {
})
.onSuccess(function() {
alert( "onSuccess" );
})
.fail(function() {
alert( "error" );
});
}
So basically this code initializes the JQuery Selectable environment. When loading the module in the div, I use $('#dynamicPage').hide().load("module1.php").fadeIn('500'); directly followed by $.getScript("participation.js");
The thing is, the module correctly loads (at least the HTML part), and I can see in the console log ("initSelectable"). But I need to manually re-execute initSelectable() from the command for it to be effective. And when I do that, I see there's an undefined getting logged in the console, before the second ("initSelectable") log (this might be due to the fact that I'm trying to call $('#selectable').selectable(); a second time).
For example, here is the participation module .php file:
<div class="well">
<h3>Create a participation</h3>
<h4>Please select <span id="selectedPlayersCount">8 players</span></h4>
<div class="row">
<div class="col-sm-4">
<ol id="selectable">
<?php include_once "../Ctrl/rankingList.php" ?>
</ol>
<button class="btn btn-success" id="submitParticipationBtn" onclick="submitParticipation()">Submit</button>
</div>
</div>
</div>
I've tried countless different way to call the initSelectable function (callbacks, events, timeOuts, etc...) and no matter what, even if it gets executed by the browser, I still need to manually re-execute it for it to be working...
So basically, my question is:
What is the correct way to load HTML and dependant JS files into a div ?
What is the correct way to load HTML and dependant JS files into a div ?
So, this would be a good start and you can take it from here.
$(function() {
$("#myDiv").load("myfile.php", function() {
console.log("HTML has been injected!");
//Get dependencies
$.getScript( "myscript.js" )
.done(function( script, textStatus ) {
//Call methods from within myscript.js
initSelectable();
})
.fail(function( jqxhr, settings, exception ) {
console.log("There was an error!");
});
});
// Remove inline event handler and bind it like below.
$("#myDiv").on("click", "#submitParticipationBtn", submitParticipation);
function submitParticipation() {
//...
//...
}
});
I am not sure why $('#selectable').selectable() is being duplicated. But, it's left you to fix :)
Okay so I was doing it wrong. I thought that putting the <script src "path/to/script.js"></script> in the module file didn't work. But actually, it does, and I simply needed to call $(document).ready(initSelectable()) in the JS file to be sure the initSelectable was executed at the right time.
So now my .php file looks like this:
<div class="well">
<h3>Create a participation</h3>
<h4>Please select <span id="selectedPlayersCount">8 players</span></h4>
<div class="row">
<div class="col-sm-4">
<ol id="selectable">
<?php include_once "../Ctrl/rankingList.php" ?>
</ol>
<button class="btn btn-success" id="submitParticipationBtn" onclick="submitParticipation()">Submit</button>
</div>
</div>
<script src="../Ctrl/participation.js"></script>
</div>
Thanks all for your help :P

Update list of divs after ajax post

I have this code that loads some div
<input class="input-large" placeholder="Notat" id="txtNewNote" type="text">
<button class="btn" id="btnAddNote" type="button">Lagre</button>
#foreach (var item in Model.UserNotes)
{
<div class="alert" id="divNote-#item.UserNoteID">
<button type="button" class="close" onclick="NoteDeleteClicked(#item.UserNoteID)" id="btnCloseNote">×</button>
<strong>#item.User.Name - #item.Added</strong><br />
#item.Text
</div>
}
Then I run this javascript when the user enter more text:
var Text = $("#txtNewNote").val();
var Added = Date.now();
vvar UserID = $("#hiddenUserID").text();
$.post("/api/apiUserNotes",{ Text : Text, Added: Added, UserID: UserID }, function() { //need functianality for updating the list of divs above });
Anyone can point me in the right direction here. I cannot just create the div after the post are done because I need to fetch data from the database so that the information in the div are correct.
There are mainly two approaches:
apiUserNotes returns HTML - This approach is a bit easier to maintain since you have only one template. But it is also more restricting in the sense that HTML is good for showing, but not so much for manipulating it.
apiUserNotes returns JSON - This is more flexible since a JSON API can be consumed by pretty much anything, from HTML to native iOS or Android apps, as it's much easier to manipulate. It's also more work though, as you then have templates both on the server-side (your Razor view) as well as on the client-side (your HTML/JavaScript).
This is more or less what #1 would look like:
You first make a partial view to display user notes:
_UserNotes.cshtml:
<div id="user-notes">
#foreach (var item in Model.UserNotes)
{
<div class="alert" id="divNote-#item.UserNoteID">
<button type="button" class="close" onclick="NoteDeleteClicked(#item.UserNoteID)" id="btnCloseNote">×</button>
<strong>#item.User.Name - #item.Added</strong><br />
#item.Text
</div>
}
</div>
Once you have this partial view, you can consume it from your view:
<input class="input-large" placeholder="Notat" id="txtNewNote" type="text">
<button class="btn" id="btnAddNote" type="button">Lagre</button>
#Html.Partial("_UserNotes")
And from your apiUserNotes action:
public PartialViewResult apiUserNotes(string text, DateTime added, int userID)
{
// TODO: save new note
var notes = yourRepo.GetUserNotes(userID);
return PartialView("_UserNotes", notes);
}
Finally, your client-side scripts simply overrites the div containing all user notes:
var data = {
text = $("#txtNewNote").val(),
added = Date.now(),
userID = $("#hiddenUserID").text()
};
$.post("/apiUserNotes", data, function (result) {
$('#user-notes').html(result);
});
There are of course much more efficient ways of doing this. For example, you don't need to reload all user notes; only the one your just added. But hopefully this gets you started.
You can access above Divs in following way, and update as per your requirement.
$.post("/api/apiUserNotes",{ Text : Text, Added: Added, UserID: UserID },
function()
{
//need functianality for updating the list of divs above
$("div.alert").each(....)
});

Categories