I'm working in a project with vue-cli and they want me to generate a listlike view (pun intended) onto data from the database.
I've never really worked with vue. 4 months ago I was given some time to find my way into it, but then I had to work on our lumen-driven backend api and so I forgot most of the stuff. And besides that, I really find vue utterly confusing.
So I need to do this step by step since I dont have loads of time at hand to throughly learn the framework before actually producing usable results.
I have the following template:
<template>
<div>
<h1>myList</h1>
<table id="testTable"></table>
<button class="button" v-on:click='fetchList'>myButton</button>
</div>
</template>
<script>
import store from "../store/store";
import { USER_FETCHLIST } from "../store/actions/user";
export default {
data () {
return {
}
},
methods: {
fetchList: function(){
var test = store.dispatch(USER_FETCHLIST).then((res)=> {
console.log(res)
document.getElementById("testTable").InnerHTML = res
})
}
}
}
</script>
<style>
</style>
The fetchList() successfully fetches the data from the DB. But I cant insert anything into my table element, at least not this "javascript-way" which I tried in the above code.
For example, when I try to input this string: <tr><td>1</td><td>2</td></tr> into the table element, nothing happens.
I learnt about v-bind and all this stuff, but I really don't know how to implement it here.
I also must emphasize that I absolutely want to avoid building this component from subcomponents.
The "inheritance" in vue.js is pretty different from the usual inheritance in programming and I really tried to get my head around it, but I just cant make anything useful with it in my relatively short timeframe.
So I need to have all the JS and html in place in this component.
Can anyone give me a hand in propery binding the prefabricated HTML-String to the table element?
Thank you!
Related
I am loading server response in a datatable using js in a asp.net core razor page. Because the data/UI is complex, I need to render different layouts based on current value in each table cell.
Datatable supports a renderer function for each cell, so I could have something like:
...
"data":"somefield",
"renderer":function(data,type,row,meta){
if (data.someId)=="someValue"{
return "<div... some label with somValue</div>"
}else{
return "<div... some label without value</div>"
}
}
}
This works perfectly fine, however when divs get complex with style and many labels it becomes harder to maintain or change.
I did look a bit into Razor's PartialViews as it may seem like a good alternative. Having the UI in a cshtml file, being able to pass parameters from parent #Model and using c# in it to render it based on the parameter received.
While I am able to load the partial view in the parent page, using <partial name=''/> or #Html.Partial(...) I didn't manage to get it's content in js using $.get and return it in the datatable's render function. Probably async wouldn't work in this case? Or it would be too slow?
My question is: what would be a better way to handle this situation? Maybe partial views are not the way. I am looking for a way of easily maintaining/changing the cell content. Thank you for your time.
I'm not really familiar with asp.net but I will try to answer your question.
I don't think PartialViews are going to work in the way you suggest because they appear to be server-side code, and trying to do a GET request for every line in your table could potentially generate a large number of server requests.
I think you have a couple of potential solutions. First is to loop through your data on the server, and for each property that matches the condition generate the partial view and assign it to the property. Then return your data array with one of the properties in each row being a chunk of HTML. As I said, I don't have experience with this language so it's hard for me to provide a code example, but I hope you understand what I'm trying to say. Then in DataTables you just need to output the value
columns: [
{ data: 'someField' }
]
THe second option is to generate the HTML on the client using JavaScript. Since you say that it could be complex it's best if you have a function that returns a HTML string. If it's a large amount of HTML then you could even put this function in a separate file and export it, to make it more manageable. There are a couple of typos in your example, so I'm going to fix them here. Renderer is a table property, the one you want is columns.render. Also in the render function the data argument references the data property that is defined in the line above. If you want to reference a different property, use the row argument.
columns: [
{
data: 'someField',
render: (data, type, row) => renderMyData(data, row)
}
]
function renderMyData(data, row) {
if (row.someId == "someValue") {
return "<div...> some label with somValue</div>"
} else {
return "<div...> some label without value</div>"
}
}
Overview
Im learning Angular and JHipster trying to get the id of an objet in a collection.
but I can't get the event click to work on the panel also a I can't use the panelChange event on the panel itself.
Is a DAFO analysis so i need the id to get the elements
My thoughts
think im donning wrong the binding or im using a different event
this is in the TypeScript side of the component
ngOnInit() {
this.activatedRoute.data.subscribe(({ planEstrategico }) => {
this.planEstrategico = planEstrategico;
this.idPlan = planEstrategico.id;
this.cargarAnaliziFoda(this.idPlan);
});
}
cargarElementosFoda(id) {
console.log(id);
}
first I try this
<ngb-panel
(click)="cargarElementosFoda(diagnosticoFoda.id)"
*ngFor="let diagnosticoFoda of diagnosticoFodas"
>
dint work so I try this
<ngb-panel
(panelChange)="cargarElementosFoda(diagnosticoFoda.id)"
*ngFor="let diagnosticoFoda of diagnosticoFodas"
>
also don't work
I read only works on the ngb-accordion
but the problem is not all the panels are for DOFA just one or two.
Questions
Best way to get the id of my collection with click event?
Alternative ways to get the id? maybe on the typescript side of the
component
Notes
im really new on Angular, TypeScript and Jhipster please if I miss something important let me know it on the comment I will added to the question.
I'm using React and created a small page that has 4 components (React classes, what is the preferred term? I'll call them components in this post):
Component Breakdown
a parent "App" component that includes and manages the other components
a "Form" component that lets the user interact with the page
a "String View" component that displays the input from the form as text
a "Visual View" (I know, bad name...) component that interprets the string view and performs actions to adjust the visual.
Dataflow
The communication of these components using states and props is as follows:
The Form has onChange handlers that pass the new state to the App
The App funnels the state data to the String View
The String View updates and passes the updated state to the App
The App funnels the new state data to the Visual View
Finally, the Visual View now updates based on the new state.
Sample Code
var App = React.createClass({
handleFormChange: function(formData) {
this.setState({formData:formData});
},
handleStringChange: function(stringData) {
this.setState({stringData:stringData});
},
render: function() {
return (
<div className="app">
<FormView onFormChange={this.handleFormChange}/>
<StringView formData={this.state.formData} onStringChange={this.handleStringChange}/>
<VisualView stringData={this.state.stringData}/>
</div>
);
}
});
var FormView = React.createClass({
handleFormChange: function(e) {
this.props.onFormChange(e.target.value);
}
render: function() {
return(
<div className="formView">
<select onChange={this.handleFormChange}>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</select>
</div>
);
}
});
var StringView = React.createClass({
componentDidUpdate: function() {
this.props.onStringChange({newString:'newStringState'});
},
render: function() {
this.props.formData;
// process formData and update state
return (
<div className="stringView">
{this.props.formData}
</div>
);
}
});
var VisualView = React.createClass({
render: function() {
var selection = this.props.stringData,
output = '';
if (selection === 1) {
output = 'Hooray, 1!';
} else {
output = 'Yes! 2!';
}
return (
<div className="stringView">
{output}
</div>
);
}
});
Questions
Is this the correct dataflow paradigm that React is trying to enforce (components only talk to parents, not siblings)?
Compared to how I would have written this in just regular JavaScript, this seems terribly constrained. Am I missing the big picture? Is this dataflow paradigm designed to prevent future problems (if so, which ones? Any that can't be solved with disciplined regular JavaScript?), or is there some other purpose that I'm missing?
I'm getting a lot of repeated function names (handleFormChange for example, it's used in App and Form View), is there a good way to make these distinguishable? Or, are repeated function names across components desirable?
When the components actually build, the JSX stuff gets transpiled down into real JavaScript. Is there an advantage to using JSX? Would writing components in the already transpiled JavaScript have an advantage?
To start, I think it is ok to call "components", and I've seen lot of people call that way. I will answer your questions below, in an order that I think is better to make my answers make sense.
When the components actually build, the JSX stuff gets transpiled down into real JavaScript. Is there an advantage to using JSX? Would writing components in the already transpiled JavaScript have an advantage?
JSX kinda mixes JavaScript and HTML, so, it makes your code "friendly". You will create your components, and just "call" them as HTML tags. Below you can see the difference between writing JSX and pure JavaScript.
return <div className="my-component"><p>Awesome</p></div>;
return ReactDOM.div({
className: 'my-component'
}, ReactDOM.p({}, "Awesome"));
I don't know you, but I would get tired to write this amount of code just to render a div with a paragraph.
You can check more benefits of using it here:
https://hchen1202.gitbooks.io/learning-react-js/content/benefits_of_jsx.html
I'm getting a lot of repeat function names (handleFormChange for example, it's used in App and Form View), is there a good way to make these distinguishable? Or, are repeated function names across components desirable?
It is not bad, also, your app is a "demo" one, if it would be a "real" one, it would have some better names for the components (i.e. <FormView> would be <ContactForm>) and maybe your method names would be different. But it is not bad at all. For example, inside <ContactForm> you may call the submit handler as onSubmit, but outside (the prop that you pass), you may call onContactFormSubmit, or, in a more semantic way, onContactFormFilled.
If your application starts to grow and you have lots of things repeated in the same component (that is the case of your <App>), you may try to split your components, therefore, each of your component will "know" about a "domain", and it would not appear to have lots of repeated stuff.
Is this the correct dataflow paradigm that React is trying to enforce (components only talk to parents, not siblings)?
First of all, React doesn't "enforce" anything, as some people say, React is the "v" in MVC, so, you have your "presentation" layer described as components, and the data may flow in the way you want.
But you got a point when you say "components only talk to parents, not siblings", because that is the way you can "communicate" between your components when you have multiple components. Since a component can't see its sibling, you need someone to orchestrate this communication, and, in this case, this is the parent's job.
There are other ways to make components "talk" to each other (i.e. using refs), but having a parent to orchestrate is, IMO, the most reliable (and better testable) one.
Compared to how I would have written this in just regular JavaScript, this seems terribly constrained. Am I missing the big picture? Is this dataflow paradigm designed to prevent future problems (if so, which ones? Any that can't be solved with disciplined regular JavaScript?), or is there some other purpose that I'm missing?
I decided to answer that as the last one, to sum up some things.
IMO, React is just great, you start to have your "logic" in the right place (a component), and you can just compose things in order to make your page work well (and by well I mean it is orchestrated correctly).
React also makes it easier to "think" about how you will build your interfaces. This Pete Hunt's blog post is amazing, and you should check it out:
https://facebook.github.io/react/docs/thinking-in-react.html
If you would be writing your code with plain JavaScript, you would have to handle DOM in some way (i.e. using a template engine) and your code would end up mixing DOM manipulation with your application logic. React just abstracts that for you. You can only care about presenting stuff. Another advantage is that, when everything is a component, you can reuse those components, it doesn't matter where they are located. If you pass the props correctly, your component will work as expected.
I know it seems exhaustive to write those components, but as you start to write more components you start to see lots of benefits. One of them is to nevermore wonder about how to present your data (no more concatenating HTML strings or calling template functions). Another one is that it is easy to "split" your interfaces, what makes your code easier to maintain (and that is not straightforward when using plain JavaScript).
To be honest, this application you wrote is really simple, and you may not see lots of advantages of using React for building it. I think you should try to create a more "complex" one, and compare it with plain JavaScript. By "complex", I mean "user interface" complex. For example, create a form that allows user to submit multiple "people". And "people" should have "name" and multiple "pet" (which also have a name). You will see how hard is it to handle "add" and "remove" operations in this case, and how easy React handle that kind of thing.
I think that is it, I hope you and React "click". It changed my mind about how to create complex user interfaces.
A week ago I ran into a problem with emberjs and DataTables.
I was using ember-data to get data from the asp codebehind using webmethods based on the route parameters. Then I would use that data to create a table with datatables. However, when I changed the route, which changed the data and therefore changed the html, datatables would add the rows, but it wouldn't remove the old rows. In addition none of the functionality would work on the new rows and whenever I would sort, it would remove the new data.
Please let me know if anyone has a better answer than the one I posted.
I looked and found a lot of questions on this topic, or similar topics; However all of the solutions were hacky or costly performance-wise. So I found my own.
It isn't perfect; I would love for ember to implement an event based on this.
I added a controller initially for navigating in my application view. The change event looks mostly like this:
paramsChanged: function () {
if (this.type && this.filingType.value && this.year && this.period) {
this.transitionToRoute('application');
Ember.run.next(this, function () {
this.transitionToRoute(this.type.value, this.year, this.period);
});
//console.log('persist');
}
}.observes('type', 'year', 'period')
This is changing the route to application(basically removing the sub view) then moving to whichever route I need next.
The performance cost, although untested, should be negligible. I need to run the code for creating the view anyway, and I'm already in the application. I'm destroying a little bit extra by transitioning to the index, then I'm recreating the sub-view on the next run loop causing the initialization code contained in didInsertElement to be run.
Looking at the Virtual DOM in React.js and by doing a few performance tests, I'm very interested in this library. It seems like the perfect add-on to Backbone's awesome model, router and collection structure.
However, due to the lack of quality tutorials and courses out there, I'm left with a few questions I hope someone here will be able to answer:
HTML templates
Does React completely do away with the notion of HTML templates? I'm talking about having your view markup in a separate HTML file (Or on the same page in a <script type=text/template> tag). You know, like you do with underscore.js Handlebars etc ...
The Starter kit examples all seem to have the JSX or React.DOM functions right inside your view classes, which seems a little messy to me, and I can see this getting a little out of hand, as your views grow in complexity.
Here's an example that renders 2 values and the sum of them, using a basic Twitter Bootstrap panel element with a nested table.
var CustomView = React.createClass({
render: function() {
var x = this.props.x;
var y = this.props.y;
return (
<div className="panel panel-primary">
<div className="panel-heading">
<h1 className="panel-title">Should I put all this markup somewhere else?</h1>
</div>
<div className="panel-body">
<table className="table">
<thead>
<tr>
<th>X</th>
<th>Y</th>
<th>Combined val</th>
</tr>
</thead>
<tbody>
<tr>
<td>{x}</td>
<td>{y}</td>
<td>{x + y}</td>
</tr>
</tbody>
</table>
</div>
</div>
);
}
});
I'm not interested in knowing whether it's possible or not to move this stuff to a separate file, rather, I'm trying to understand what's considered the best practise when working with React.
Updating and setting data
The Why React page states the following:
Simply express how your app should look at any given point in time, and React will automatically manage all UI updates when your underlying data changes.
I'm not fully understanding how this works. For instance, take the React component from before <CustomView x="20" y="10">. Initially I would render it like so:
var x = 20;
var y = 10;
React.renderComponent(
<CustomView x={x} y={y} />,
document.getElementById('view-container')
);
Now, when I want to update CustomView any time x changes, how should I proceed? React is supposed to be an alternative to the data binding you find in Angular and Ember, without doing a 2-way binding, so how do I make this happen? How do I tell CustomView to keep an eye on x and automatically re-render when it changes?
Naturally, just assigning x a new value does nothing.
I know there's the setState method, but I still manually have to call that, right? So if I was working with a React view and a Backbone model, the code could look something like this:
// Data model: Backbone.js
var model = new Backbone.Model({text: "Please help! :)"});
// Create view class
var View = React.CreateClass({
render: function() {
return (
<p>{this.props.text}</p>
);
}
});
// Instantiate new view
var view = React.renderComponent(
<View text={model.get("text")}>,
document.getElementById('view-container')
);
// Update view
model.on("change:text", function(model, newValue) {
view.setState({
text: newValue
});
});
// Change data
model.set("text", "I do not understand this ...");
That seems like a really strange setup, and I'm almost sure this can't be the way you're supposed to do it.
I would love some pointers to help me move in the right direction here.
Thank you in advance for any feedback and help.
Does React completely do away with the notion of HTML templates?
Yes, in favor of declaring your views with JavaScript. It also allows the Virtual DOM structure to work efficiently.
The Starter kit examples all seem to have the JSX or React.DOM functions right inside your view classes, which seems a little messy to me, and I can see this getting a little out of hand, as your views grow in complexity.
You shouldn't allow your view to grow in complexity. Make big components from small components, and you won't have an issue. If you feel it's getting complex, you can always reorganize it.
I know there's the setState method, but I still manually have to call that, right? So if I was working with a React view and a Backbone model [...]
You should search for "react backbone", and you'll find some blog posts and code examples. They're often used together. Feel free to add any links you found helpful here.
You're on the right path, however there are two things to fix. One is a bug, the other is a preferred pattern.
The bug: In the View, you are using this.props.text (good!), but you are using setState in the model listener. This sets the this.state.text value, which you are not using, so it won't work. setState should 'only' be used from inside the component itself - for all intents and purposes, think of it as a protected method. Instead, there is the setProps function, which is intended to be used only from outside the component.
The preferred pattern: The usage of setProps will soon be deprecated, as it causes a number of subtle issues. The better thing to do is just re-render the whole component each time. The right code in your case is:
// Data model: Backbone.js
var model = new Backbone.Model({text: "Please help! :)"});
// Create view class
var View = React.CreateClass({
render: function() {
return (
<p>{this.props.text}</p>
);
}
});
function rerender() {
React.renderComponent(
<View text={model.get("text")}>,
document.getElementById('view-container')
);
}
// Update view
model.on("change:text", function(model, newValue) {
rerender();
});
rerender();
Thank you for the replies guys,
So, am I correct in assuming that if I want the views to observe the data models, what I end up with is actually pretty close to Backbone view code, where you hook up event listeners in the intialize method? Here's a quick example that works:
var model = new Backbone.Model({
text: "Hey there :)"
});
var TextBox = React.createClass({
getInitialState: function() {
return this.props.model.toJSON();
},
componentWillMount: function() {
this.props.model.on("change:text", function(model, newText) {
this.setState({
text: newText
});
}, this);
},
render: function() {
return (
<p>{this.state.text}</p>
);
}
});
React.renderComponent(
<TextBox model={model} />,
document.getElementById('view-holder')
);
As I said this does work as intended. The view re-renders whenever the model's text property changes. Would this be considered "Good" React code, or should I hook this up differently?