Chosen is working great for me but I cannot figure out how to get my acceptance test to send in the value on the form submit.
Handlebars template:
<form>
{{#ember-chosen value=country}}
{{#each countries as |country|}}
<option value={{country}}>{{country}}</option>
{{/each}}
{{/ember-chosen}}
{{#link-to 'countries.show' (query-params country=country) tagName='button' type='submit' replace=true class="submit__button"}}Search{{/link-to}}
</form>
Acceptance test:
test 'Searching for a country', (assert) ->
visit '/search'
find('.chosen-select').val('USA')
find('.chosen-select').trigger('chosen:updated')
click('.submit__button')
andThen ->
assert.equal find(".chosen-select :selected").text(), "USA"
This fails because on submit country is not even passed in as a query param, but only in the test.
The same thing happens if I do it in the console. If I open my console and do:
$('.chosen-select').val('USA')
$('.chosen-select').trigger('chosen:updated')
then the selection updates before my eyes! But then clicking submit produces the same results as the test, that is, the country is not passed into the query-params.
Clicking "USA" from the dropdown however, then clicking submit, works perfectly.
UPDATE
Chad Carbert's response below gave me the answer. Here are the specific results:
$('.chosen-select').val('USA')
$('.chosen-select').trigger('chosen:updated')
updates the DOM only. Not the data-bindings with Ember.
$('.chosen-select').trigger('change', {'selected': 'USA'})
updates the data-bindings (which is what I really need), not the DOM.
Since this is for my acceptance tests only and I don't need to see the DOM change, my test now looks like this:
test 'Searching for a country', (assert) ->
visit '/search'
find('.chosen-select').trigger('change', {'selected': 'USA'})
click('.submit__button')
andThen ->
assert.equal find(".chosen-select :selected").text(), "USA"
Which works like a charm! If you wanted to though, there would be no harm in doing all three:
test 'Searching for a country', (assert) ->
visit '/search'
find('.chosen-select').val('USA')
find('.chosen-select').trigger('chosen:updated')
find('.chosen-select').trigger('change', {'selected': 'USA'})
click('.submit__button')
andThen ->
assert.equal find(".chosen-select :selected").text(), "USA"
Thank you Chad!
It looks like this might be an issue with the way that this component wraps the jQuery library. Looking at the documentation for chosen:
Updating Chosen Dynamically
If you need to update the options in your select field and want Chosen to pick up the changes, you'll need to trigger the "chosen:updated" event on the field. Chosen will re-build itself based on the updated content.
via chosen docs
However, it doesn't look like the ember component is wrapping that event in any way. It also looks like the chosen:update is updating the chosen UI implementation, but not the data binding within Ember. This would be in a case where you've after the fact added options to the select, and want these reflected ('rebuilt') on the screen.
Looking at the code behind this component and how it's wrapping the chosen library, it appears that this component is only capturing the change event. So try doing a trigger on a change event and that should have things update within ember, and its data binding.
Or try triggering the change the way it's mentioned on the Chosen docs:
Form Field Change**
When working with form fields, you often want to perform some behavior after a value has been selected or deselected. Whenever a user selects a field in Chosen, it triggers a "change" event* on the original form field. That let's you do something like this:
$("#form_field").chosen().change( … );
If that doesn't work, if you're able to provide a codepen I will take a look closer, thanks!
Related
I am a little confused because this seems to be such a trivial and easy thing, yet there is hardly any proper documentation in Enzyme on how to do this.
I want to do one of the simplest things in the world. I just want to simulate a select event in a drop down select (HTML select/combo) by selecting an option called "dogs".
When I have this option selected would like to see that the option is "selected", and I would also like to see that the select value is set to "dogs".
What am I doing wrong here?
import React from 'react';
import {shallow, mount} from "enzyme"
test(' change ', () => {
let Compoment =
<select className="sel" name="selectComp" required="">
<option value="empty">Please make your choice ...</option>
<option value="cats">feline</option>
<option value="dogs">canine</option>
</select>;
const wrapper = mount(Compoment);
let sel = wrapper.find(".sel").at(0)
sel.simulate('change', { target: { name: 'selectComp', value: "dogs" } });
expect(wrapper.find(".sel").at(0).getElement().value).toBe("dogs")
expect(wrapper.find(".sel").at(0).find("option").at(2).props().selected).toBe(true)
})
React syncs prop=>DOM property only one way.
If you set selected prop on <option> element React would write it into DOM selected property(but you actually don't use selected prop at all).
You browser(or JSDOM in case of Jest tests) also changes selected property for relevant <option> element upon user selection.
So that's why prop does not reflect change.
You can use getDOMNode to access underlying DOM node:
expect(wrapper.find(".sel").at(0).find("option").at(2).getDOMNode().selected).toBe(true)
but know what? you don't need that. This would just test browser highlights right option upon user selection. It's just a wasted time to check if browser and/or React do their job responsibly.
This Ember template code...
<div class="detail bedrooms">
<span>Number of bedrooms:</span> {{rental.bedrooms}}
</div>
<div class="detail temperature">
<span>Current Temperature:</span> {{city-temperature location=rental.city}}
</div>
...results in this rendering...
How could one get the "25C" text to render on the same line as "Current Temperature" in the same way that "San Francisco" is on the same line as "Location"?
I have tried getting the city-temperature component to return only text, but (secondary question here) is it even possible for a component to return only text if the text is from a remote ajax request since the promise seems to need a DOM element to append to?
This Ember app is available here on GitHub. It's a modified version of the official Ember.js tutorial app with this "Current Temperature" detail added.
The problem is that; city-temperature is a component; and by default ember components is assigned div as their tags. Due to this; the content of city-temperature starts at a new line.
What can you do? Play with css and make sure div tag of city-temperature does not start at a new line; but instead floating right within the owner div. The second option is making city-temperature component tagless; so that it does not start at a new line. To achieve that; you can just declare:
tagName: ''
within city-temperature.js. You can see the following twiddle to see the second option I mentioned.
After reading your comments; I have forked your repository and made minor modifications to achieve what you want. You can check my repository and my corresponding commit to see what I changed.
Basically; I really did not like the idea that weather service is returning a DOM element. I have changed it to return an instance of ember promise (I mean Ember.RSVP.Promise). Within city-temperature.js I just set a retrieved weather value from weather service and set it to the component instead of making DOM modification. Finally; I modified city-temperature.hbs to render weatherValue and added a simple css item in order to prevent weather-container div to insert a new line break.
I am not sure; whether you will like my solution or not; but I guess you will retrieve the visual appearance you want. You can always rely on promises for async tasks; you do not need to create DOM elements and pass them around to components and append them to somewhere within DOM tree of the corresponding component. I believe one of the reasons we are making use of a framework like Ember is to prevent such DOM modifications. Best regards.
An ember component adds a div by default. If you don't want to add this div tag, you need to set tagName to an empty string.
That's called tagless component.
Further, for your case, you can give a tagName='span' so you will not need a span in your template.
export default Ember.Component.extend({
tagName: 'span',
classNames: ['weather-container'],
weather: Ember.inject.service(),
//rest of your code...
});
I am trying to implement a simple search feature, which will filter the results and update the listing.
I tried almost every single tutorial out there, every tutorial seems to be working with its jsfiddle but when I apply the same thing on my project, it does not work at all.
Here is what I am having as a first problem, my search field does not seems to be bound with computed property in controller.
I also tried it as a component but again same issue, if I type anything in search field it does not reflect anything.
Let me share my code here,
input type="text" value=searchText placeholder="Search..."
searchResults: ( ->
console.log "On every key press it should come here.."
model = #get('model')
searchText = #get('searchText')
filterByPath = #get('filterByPath')
visualPath = #get('visualPath')
if searchText
searchText = searchText.toLowerCase()
model = model.filter(item) ->
Ember.get(item, filterByPath).toLowerCase().indexOf(searchText)>= 0
model.getEach(visualPath)
).property('searchText')
Tried almost the same thing with component, but no luck so far. I am not using handlebars but Emblemjs.
You actually need to use computed property in template if you want it to be compiled, then recompiled etc. It is somewhat lazily evaluated so you can't debug that without using this in template first or calling from JavaScript code. So basically you need to use searchResults in your template first.
In demo there was model instead of searchResults. I guess in your application you have similiar setup and same bug.
Fix:
{{#each searchResults as |item|}}
<li>{{item}}</li>
{{/each}}
Working demo.
I studied the Crispy-Forms documentation and I tried to put an extra button into one of my forms. With
self.helper.add_input(Button('back', "Back", css_class='btn'))
I can add a nice button. But the Button() wont take an onclick or on_click-attribute. So how can I add logic to this button? Adding an onclick event with JQuery isnt a very nice solution...
Thanks!
Ron
Are you certain that Button will not take onclick in its kwargs?
I just added an onclick="javascript here" to a Submit() element and it displayed fine.
I also peered a bit at the underlying code, and I think all inputs by default flatten the kwargs that aren't popped because of special use (i.e. template), and pass those through into the rendered HTML. This may be new since April '12 (when originally posted), but it currently seems to be as simple as the following:
self.helper.add_input(Button('back', "Back", css_class='btn', onclick="alert('Neat!');"))
This is not included by default (afaik..).
If you just need this once, is possible to use crispy-forms HTML Layout Object
HTML('<input type="button" name="Save" onclick="do_whatever" />')
What do you then dislike using jQuery? You could handle this rather easy and generic, using something like:
$('form :submit.ajax_submit').live('click', function(e) {
e.preventDefault();
var my_form = $(this).parents('form');
// do whatever
alert(my_form.attr('id'));
alert(my_form.attr('action'));
});
and then just pass the class:
Submit('save', 'save', css_class='ajax_submit')
I'm working with ASP MVC4 jquery calendar. I'm new to this. I have my jquery calendar built so that it highlights particular dates which i passed through array. But now the question is, I have a table of data in database which I got into Model and then used to it retrieve information based on an 'ID' in controller and returned to VIEW. Now I can get the dates from database in the form of table but I want to know, how I can pass those particular dates to an array of JQUERY CALENDAR in VIEW.
Also I imported package:
with core and datepicker functionalities.
But when i click the next arrow or previous arrow, it doesn't show next or previous months.
I can post the code if you don't understand my question. Please help me since I have already spent more than 15 days understanding this.
well, thats an older question but I had a couple of problem myself with datepicker and took me about 3 hours of research until I found the answer ... this is only for poeple like me who'd end up on this while digging up for answers ... *
Jquery UI is already include in .net mvc4, as is datepicker, its in the bundle. you just have to call it by adding this to your layout ( in the head section )
#Scripts.Render("~/bundles/jqueryui")
#Styles.Render("~/Content/themes/base/css", "~/Content/css")
also, make sure you dont have another script render at the bottom of your body, as its by default where the jquery bundle is set (at least it was for me on the default project ) and it cause a bug with datepicker when I used it.
<input id="mydate" name="mydate" class="datepicker" type="text" value="#Model.mydate.Value.ToString("dddd, dd MMMM yyyy")" />
where mydate is the name of the parameter you'll have set in your viewModel, said parameter is a DateTime object ( or DateTimeOffSet ) (the .Value is only if you set the date as a nullable, its not necessary otherwise)
After on the bottom of your view, create a jquery section :
#section scripts{
<script>
$(".datepicker").datepicker({ dateFormat: "DD, d MM yy", altFormat: "yy-mm-dd" });
</script>
}
(dateformat and altformat are optional, give them the value you want or dont use them at all)
as for the array of date ... i'd use a viewmodel, which would contains your array as parameter, and pass this viewmodel between your view and your controller. after that define an Editor template and its should be pretty straighforward to build a table with the dates from there.