svelte keep updating store var without clicking to update - svelte-3

My app automatically update $content value without me clicking on buttons. I know it is a simple question, but I can't find out why, I'm learning svelte.
App.svelte
<script>
import { content } from './store.js';
import Item from './Item.svelte';
$content = [{ id:0,obj: "Fell free to browse any category on top." }];
function addContent(value) {
$content = [{ id:0,obj: value}]
}
</script>
<li><button on:click={addContent("Home Page")}>Home</button></li>
<li><button on:click={addContent("Products Page")}>Products</button></li>
<div class="Content">
<p>Fell free to browse any category on top.</p>
{#each $content as item}
<p><svelte:component this={Item} objAttributes={item} /></p>
{/each}
</div>
store.js
import { writable } from 'svelte/store';
export let content = writable({});
Item.svelte
<script>
import { fade } from 'svelte/transition';
export let objAttributes = {};
</script>
<p transition:fade>
{objAttributes.obj}
{#if objAttributes.otherattrib}<em>{objAttributes.otherattrib}</em>{/if}
</p>

This is because your on:click events are defined wrongly.
The on:click takes as argument a function like this
<button on:click={functionGoesHere}>
or, if you want it inlined
<button on:click={() => { }>
What happens in your case is that you directly call a function and the result of this function will then be called when the button is clicked. You can see that in this example:
<script>
function createFn() {
return () => console.log('logging this')
}
</script>
<button on:click={createFn}>Click here</button>
in this example the function () => console.log('logging this') will be attached the button.
So to come back to your code, this is easily fixed by making it a function instead of a function call:
<li><button on:click={() => addContent("Home Page")}>Home</button></li>

Related

How to get the url to insert as a data with Redux Form?

I was able to get the url in the attachment field but for the redux form it was empty, how is possible to pass the value of the url to the redux form? Below is the code and the screenshot:
<div className="FileUpload">
<Dropzone
onDrop={this.onImageDrop.bind(this)}
multiple={false}
accept="image/*">
<div>Drop an image or click to select a file to upload.</div>
</Dropzone>
</div>
<div className="form-group">
<label htmlFor="attachment">Attachment:</label><br />
<input className="form-control" focus placeholder="attachment" type="text" name="attachment" ref="attachment" value={this.state.uploadedFileCloudinaryUrl} />
{this.state.uploadedFileCloudinaryUrl === '' ? null :
<div>
<p>{this.state.uploadedFile.name}</p>
<img src={this.state.uploadedFileCloudinaryUrl} alt="" />
</div>}
</div>
<div className="ui small image">
<img src={this.props.workrequest.attachment} alt="" />
</div>
the url in the attachemnt field
The first one is using the React Dropzone to get the url but for the Redux Form it was empty. May I know how to do that to get the url inserts at Redux Form here? Thank you
import React from 'React';
import { connect } from 'react-redux';
import { change, reduxForm } from 'redux-form';
import Dropzone from 'react-dropzone';
class UploadForm extends React.Component {
onDrop = (accepted) => {
if (!accepted.length) return;
// start uploading
this.setState({ isUploading: true });
const formData = new FormData();
formData.append('file', accepted[0]);
axios.post('upload', formData).then(
(res) => {
this.props.dispatch(change('uploadForm', 'url', res.url));
this.setState({ isUploading: false });
},
() => {
this.setState({ isUploading: false });
}
);
};
render() {
return (
<form>
<Dropzone onDrop={this.onDrop} />
</form>
);
}
}
export default connect()(
reduxForm({
form: 'uploadForm',
initialValues: {
url: ''
}
})(UploadForm)
);
Please use this.
Actually, you must use Field component from Redux-form.
Other wise, you can change form values using dispatch and change action creator.
import { Field, change } from 'redux-form';
this.props.dispatch(change('uploadForm', 'url', this.state.url));

ReactJS not binding via map to state values

I'm working with an MVC5 project and running into an issue with React not binding an array. I had this working in an MVC Core project, but had to "regress" back to the old structure. Biggest change seemed to be in the controller, changing from JsonResult (Core MVC) to Json (MVC5) for the return type on the ajax call.
Here's the output from Chrome Developer Tools:
(removed due to lack of reputation points)
And, my code for my .jsx file:
var LineItem = React.createClass({
render: function () {
return (
<div className="gridItem">
<div className="lessLineHeight smallFont">
<div className='section group'>
<div className="col span_1_of_2" id={this.props.ordHeaderId}>
<text>{this.props.code}</text>
</div>
<div className='col span_1_of_2 text-right'>
<i className={this.props.apptIconString} aria-hidden='true'></i>
<i className={this.props.highValueIconString}></i>
<i className={this.props.hazmatIconString}></i>
</div>
</div>
<div className='section group'>
<div className='col span_6_of_10'>
<text title='Trading Partner - Client'>{this.props.tradingPartnerName}</text>
</div>
<div className='col span_4_of_10 text-right'>
<text className='overflowElip' title='Account Manager'>{this.props.accountManager}</text>
</div>
</div>
<div className='section group'>
<div className='col span_1_of_2'>
<text title={"Origin: " + this.props.originAddress + "; " + this.props.origContact}>{this.props.originAddress}</text>
</div>
<div className='col span_1_of_2 text-right'>
<text title={"Destination:" + this.props.destinationAddress + "; " + this.props.destContact}>{this.props.destinationCity}</text>
</div>
</div>
<div className='section group'>
<div className='col span_1_of_3'>${this.props.freightValue}</div>
<div className='col span_1_of_3 text-center'>
<a title='Promote Order to Load'>To Load</a>
</div>
<div className='col span_1_of_3 text-right' id={'datePlanned' + this.props.ordHeaderId}>
<text title='Pickup Date'>{this.props.dateCreated}</text>
</div>
</div>
</div>
</div>
);
}
});
var ItemList = React.createClass({
getInitialState: function () {
return { items: [] };
},
loadData: function () {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function (data) {
console.log(data);
this.setState({ items: data });
console.log(this.state.items);
$("#column1").find(".gridItem:odd").css({ "background-color": "#ddd" }).end().find(".gridItem:even").css({ "background-color": "#fff" });
}.bind(this),
error: function (xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function () {
this.loadData();
/*window.setInterval(this.loadData, this.props.pollInterval);*/
},
render: function () {
if (this.state.items) {
console.log("State has items.");
var itemNodes = this.state.items.map(function (foo) {
return (
<LineItem key={foo.ordHeaderId}
accountManager={foo.accountManager}
apptIconString={foo.apptIconString}
commodityDescription={foo.commodityDescription}
commodityId={foo.commodityId}
dateCreated={foo.dateCreated}
deliveryAppt={foo.deliveryAppt}
destContact={foo.destContact}
destinationAddress={foo.destinationAddress}
destinationAddressName={foo.destinationAddressName}
destinationCity={foo.destinationCity}
earlyDeliveryTime={foo.earlyDeliveryTime}
earlyPickupTime={foo.earlyPickupTime}
equipmentName={foo.equipmentName}
freightValue={foo.freightValue}
handlingUnits={foo.handlingUnits}
hazmatIconString={foo.hazmatIconString}
highValueIconString={foo.highValueIconString}
isHazmat={foo.isHazmat}
isHighValue={foo.isHighValue}
lateDeliveryTime={foo.lateDeliveryTime}
latePickupTime={foo.latePickupTime}
loadId={foo.loadId}
loadNum={foo.loadNum}
loadTmsStatus={foo.loadTmsStatus}
ordHeaderId={foo.ordHeaderId}
ordNum={foo.ordNum}
orderType={foo.orderType}
origContact={foo.originContact}
originAddress={foo.originAddress}
originAddressName={foo.originAddressName}
originationCity={foo.originationCity}
pickupAppt={foo.pickupAppt}
pieces={foo.pieces}
plannedEnd={foo.plannedEnd}
plannedStart={foo.plannedStart}
requiredTemp={foo.requiredTemp}
specialInstructions={foo.specialInstructions}
targetCost={foo.targetCost}
teamId={foo.teamId}
tempControlled={foo.tempControlled}
tradingPartnerNameCNum={foo.tradingPartnerNameCNum}
tradingPartnerName={foo.tradingPartnerNameClient}
transportMode={foo.transportMode}
user3gIdBookedBy={foo.user3gIdBookedBy}
user3gIdCreatedBy={foo.user3gIdCreatedBy}
weight={foo.weight} />
);
});
return (
<div className="itemList">
{itemNodes}
</div>
);
} else {
return null;
}
}
});
ReactDOM.render(
<ItemList url="/DispatchBoard/getColumn1Data" pollInterval={2000} />,
document.getElementById('column1')
);
As you can see from the image, the render: in the loadData function sees the items coming back from the ajax call, and then sets them to state, but when it comes time to map them, it does nothing.
Any ideas on what I'm not seeing?
EDIT
Here's a screen show showing the 'undefined' value(s) in one of the LineItems after failing to map properly. undefined values
EDIT #2
Here's a screenshot showing that the objects are hydrated and not being parsed. object present, not parsed
After seeing the screenshot you posted in EDIT #2
The issue is you're using different property name when accessing the data from foo while setting the properties on your component
So changing it from
<LineItem key={foo.ordHeaderId}
accountManager={foo.accountManager}
apptIconString={foo.apptIconString}
to
<LineItem key={foo.ordHeaderId}
accountManager={foo.AccountManager}
...
should do the trick
That is use the exact property name from your foo object instead of using camel cased or some other version of it.
The if condition in <ItemList> render is wrong. It should be like
if(this.state.items.length > 0)
Everything else looks fine. But, you forgot to add the key to the <LineItem> component
<LineItem key={foo.ordHeaderId}
accountManager={foo.accountManager}
... />
Here, you are passing key as a prop to the <LineItem> component but you forgot to set that key from the prop to the parent element.
var LineItem = React.createClass({
render: function () {
return (
<div className="gridItem" key={this.props.key}>
<div className="lessLineHeight smallFont">
....
)
}
})
This should remove the error/warning
From what I have experienced you can't pass key as a prop element. Remove this from you LineItem and see if it works. Let the warning persist. You can figure out a way to remove the warning later if this works.
<LineItem
accountManager={foo.accountManager}
apptIconString={foo.apptIconString}
commodityDescription={foo.commodityDescription}
commodityId={foo.commodityId}
dateCreated={foo.dateCreated}
deliveryAppt={foo.deliveryAppt}
destContact={foo.destContact}
destinationAddress={foo.destinationAddress}
destinationAddressName={foo.destinationAddressName}
destinationCity={foo.destinationCity}
earlyDeliveryTime={foo.earlyDeliveryTime}
earlyPickupTime={foo.earlyPickupTime}
equipmentName={foo.equipmentName}
freightValue={foo.freightValue}
handlingUnits={foo.handlingUnits}
hazmatIconString={foo.hazmatIconString}
highValueIconString={foo.highValueIconString}
isHazmat={foo.isHazmat}
isHighValue={foo.isHighValue}
lateDeliveryTime={foo.lateDeliveryTime}
latePickupTime={foo.latePickupTime}
loadId={foo.loadId}
loadNum={foo.loadNum}
loadTmsStatus={foo.loadTmsStatus}
ordHeaderId={foo.ordHeaderId}
ordNum={foo.ordNum}
orderType={foo.orderType}
origContact={foo.originContact}
originAddress={foo.originAddress}
originAddressName={foo.originAddressName}
originationCity={foo.originationCity}
pickupAppt={foo.pickupAppt}
pieces={foo.pieces}
plannedEnd={foo.plannedEnd}
plannedStart={foo.plannedStart}
requiredTemp={foo.requiredTemp}
specialInstructions={foo.specialInstructions}
targetCost={foo.targetCost}
teamId={foo.teamId}
tempControlled={foo.tempControlled}
tradingPartnerNameCNum={foo.tradingPartnerNameCNum}
tradingPartnerName={foo.tradingPartnerNameClient}
transportMode={foo.transportMode}
user3gIdBookedBy={foo.user3gIdBookedBy}
user3gIdCreatedBy={foo.user3gIdCreatedBy}
weight={foo.weight} />
Random User found the answer and it's contained in his comment.
The "key" to the problem was not capitalizing the properties that were to be mapped. Not sure why it worked the way it was in Core MVC, but, obviously, it doesn't work the same in MVC 4.

Content of <div> not updating

I've got a div element which I am using as a popup which does not update itself. I'll use the picture below to explain:
When I click on each row in the grid, the right hand side updates to show the details, part of which is a potentially lengthy Note field. The button View Note triggers a popup with the full text inside. Here, I have previously selected Donor 2000000, which displayed the correct note. However, when I select another Donor(2000002 as highlighted) the information in the popup retains the info for the first selected Donor. So, essentially it sets it once and then does not update.
The (partial) code for the main View is:
<div class="col-md-4 col-md-push-8">
<h4>
Donor Details
</h4>
<div id="donor-details">
<p class="muted">
Select donor to display detailed infomation
</p>
</div>
</div>
<div class="col-md-8 col-md-pull-4">
#Html.Action("DonorSummaryGrid") #* configure grid in a partial view *#
</div>
</div>
<script>
$(function () {
pageGrids.donorSummaryGrid.onRowSelect(function (e) {
$.post("/Donor/GetDonorDetails?donorId=" + e.row.DonorId, function (data) {
if (data.Status <= 0) {
alert(data.Message);
return;
}
$("#donor-details").html(data.Content);
});
});
});
</script>
The code for the partial view - which contains the details - is:
#if (!String.IsNullOrWhiteSpace(Model.CurrentNoteText)) {
<div id="note-dialog" title="Note for Donor #Model.DonorId">
<p>#Html.DisplayTextFor(model => model.CurrentNoteText)</p>
</div>
<br />
}
#Scripts.Render("~/Scripts/NoteDialogue.js")
When I debug, the value of Model.CurrentNoteText and #Model.DonorId do reflect the correct data.
NoteDialogue.js is:
$(function() {
$("#note-dialog").dialog({
autoOpen: false,
show: {
effect: "blind",
duration: 500
},
hide: {
effect: "blind",
duration: 200
}
});
$("#opener").click(function() {
$("#note-dialog").dialog("open");
});
});
I hope this is clear :)
Oh, there are no errors shown in the browser, and everthing functions as expected, except for updating the info in the popup.
I have tried
<script>
$("#note-dialog").html("#Model.CurrentNoteText");
</script>
with no success.
Got there in the end :)
Looking at the generated source, I noticed that the code for
<div id="note-dialog" title="Note for Donor #Model.DonorId">
<p>#Html.DisplayTextFor(model => model.CurrentNoteText)</p>
</div>
<br />
was being generated right at the bottom, outside all the other divs containing the grid and details. Looked something like this:
<div tabindex="-1" class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-front ui-draggable ui-resizable" role="dialog" aria-describedby="note-dialog" aria-labelledby="ui-id-1"....>
As I clicked each row with a note in, an extra div was being generated, with the aria-labelledby attribute incrementing, e.g. "ui-id-2", "ui-id-3"...
The first generated div was being selected for the dialogue opening.
The solution was to remove the div on the row click event. Code now is:
$(function() {
pageGrids.donorSummaryGrid.onRowSelect(function (e) {
$("#note-dialog").remove();
$.post("/Donor/GetDonorDetails?donorId=" + e.row.DonorId, function(data) {
if (data.Status <= 0) {
alert(data.Message);
return;
}
$("#donor-details").html(data.Content);
});
});
});

Adding events to button doesn't work with backbone

I read over 20 different articles and forum topics about that, tried different solutions but I didn't cope with it.
The following code doesn't work. I need someone's help...
LoginView.js
var LoginView = Backbone.View.extend({
//el: $('#page-login'),
initialize: function() {
_.bindAll(this, 'gotoLogin', 'render');
//this.render();
},
events: {
'click #button-login': 'gotoLogin'
},
gotoLogin : function(e){
e.preventDefault();
$('#signup-or-login').hide();
$('#login').show();
return true;
}
});
login.html
<div data-role="page" id="page-login">
<!-- SignUp or Login section-->
<div id="signup-or-login" data-theme="a">
<a data-role="button" data-theme="b" id="button-signup"> Sign Up </a>
<a data-role="button" data-theme="x" id="button-login"> Login </a>
</div>
<!-- Login section-->
<div id="login" data-theme="a">
<button data-theme="b"> Login </button>
<button data-theme="x"> Cancel </button>
</div>
</div>
The page is created in method of Backbone.Router extended class.
loadPage('login.html', new LoginView());
From what I understand, $.mobile.loadPage() grabs the desired html and attaches it to the DOM.
Currently, you're trying to set el after the View has been instantiated.
However, notice that Backbone.View attaches el and $el when it's instantiated:
var View = Backbone.View = function(options) {
...
this._ensureElement();
this.initialize.apply(this, arguments);
this.delegateEvents();
};
Also notice that View.setElement() sets $el by passing a selector or a jQuery objected to View.el:
setElement: function(element, delegate) {
if (this.$el) this.undelegateEvents();
this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
this.el = this.$el[0];
if (delegate !== false) this.delegateEvents();
return this;
}
Bottom line:
You need to set el (in your case with the provided jQuery object) while instantiating it:
// Where `view` is a reference to the constructor, not an instantiated object
var loadPage = function(url, view) {
$.mobile.loadPage(url, true).done(function (absUrul, options, page) {
var v,
pageId = page.attr('id');
v = new view({
el: page
});
...
}
}
You now call loadPage() like so:
loadPage('login.html', LoginView);
This gives Backbone.View the $el which to delegate your events.

Expressions are not evaluated in $watch of custom directive of angularjs

I have a below custom directive in angularjs which uses model thats gets updated from server,
I have added a watch listener to watch the changes of that model,
var linkFn;
linkFn = function(scope, element, attrs) {
scope.$watch('$parent.photogallery', function(newValue, oldValue) {
if(angular.isUndefined(newValue)) {
return;
}
var $container = element;
alert($container.element);
$container.imagesLoaded(function() {
$container.masonry({
itemSelector : '.box'
});
});
});
};
return {
templateUrl:'templates/Photos_Masonry.htm',
replace: false,
transclude:true,
scope: {
photogallery: '=photoGallery',
},
restrict: 'A',
link: linkFn
However, when i debug in my watch directive, i still see that expressions in templates are still unresolved.i.e. photo.label, ng-src all are still unresolved. AFIK, $digest would be called only after $eval. Is this intended behavior?
My jQuery calls are not working due to this? Is there any other event where i get the result element with evaluated expressions?
Here is my template, which has ng-repeat in it,
<div id="container" class="clearfix">
<div class="box col2" ng-repeat="photo in photogallery">
<a ng-href="#/viewphotos?id={{photo.uniqueid}}&&galleryid={{galleryid}}"
title="{{photo.label}}"><img
ng-src="{{photo.thumbnail_url}}" alt="Stanley" class="fade_spot" /></a>
<h3>
<span style="border-bottom: 1px solid black;font-weight:normal;font-size:14px;">{{galleryname}}</span>
</h3>
<h3>
<span style="color:#20ACB8;font-weight:normal;font-size:17px;">{{photo.seasonname}}</span>
</h3>
</div>
</div>
photogallery is initialized in parent controller,
function MyCtrlCampaign($scope, srvgallery, mygallery) {
$scope.updatedata = function() {
$scope.photogallery = srvgallery.getphotos($routeParams);
};
$scope.getphotos = function() {
srvgallery.photos().success(function(data) {
$scope.updatedata();
}).error(function(data) {
});
};
Directive is used in below way,
<div masonry photo-gallery="photogallery" >
</div>
Kindly let me know your views on this.
Looks like this has been resolved in your Github issue (posted for the convenience of others).

Resources