pierrickrouxel / ember-strap

DEPRECATED IN FAVOR OF https://github.com/kaliber5/ember-bootstrap
MIT License
15 stars 3 forks source link

how to implement #2

Open shopapps opened 9 years ago

shopapps commented 9 years ago

Hi Please excuse my inexperience, however could you expand on your usage instructions for me? for step 3 you have:

Call modal() within your router map, at whichever scope you choose and wire up any actions: 

what is a router map? I tried placing your example code in one of my module(pod)s route.js file and I get an error:

this.modal is not a function

which would imply to me that I need to extend something to get the route to understand it?

many thanks, and sorry for the (probably) dumb question.

Edit. So i did some experimenting I realise now you are referring to the core router.js file and the Router.map call in there. However I still get the this.modal is not a function error, which is what I would expect if we are not extending something else first? what am I missing :)

pierrickrouxel commented 9 years ago

Hi,

Sorry I did a mistake in the documentation. The method is this.esModal(). It's well in the router that you can do this.

I will correct it later. Thanks.

shopapps commented 9 years ago

ok, thanks.. but i still get the error:

this.esModal is not a function
pierrickrouxel commented 9 years ago

Your router needs to be as this:

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
  this.esModal('modal-example', { withParams: 'modal' });
});

export default Router;
pierrickrouxel commented 9 years ago

I fixed the method name in documentation

pierrickrouxel commented 9 years ago

Is it ok?

shopapps commented 9 years ago

Hi,

Sorry for not replying earlier... As mentioned even setup as you described, I still get the error

this.esModal is not a function

So I had to move on to a different solution. Thanks anyway.

pierrickrouxel commented 9 years ago

Can you answer a last question please? What is your Ember version?

shopapps commented 9 years ago

Hi,

No problem, it's version 1.13.7

pierrickrouxel commented 9 years ago

Thanks, it should work... if you want to use "ember-strap" at new I will be pleased to help you to find your problem.

shopapps commented 9 years ago

I am willing to take another look, it will be later this morning that I will be back coding the app am just working on some documentation right now. Is there anything more I can do as part of the initial install?

pierrickrouxel commented 9 years ago

I designed ember-strap to be working out-of-box. Normally there is nothing to do. I will provide you a simple project with modal example and a step-by-step readme. I'm really interested with feedback on this project.

shopapps commented 9 years ago

yep, no problem, happy to help. And would be good to get it working.

pierrickrouxel commented 9 years ago

I think I found your problem. EmberStrap is not yet released for ember 1.13+. I think you actually use ember-strap 0.0.1.

You can install the beta version:

ember install ember-strap@2.0.0-beta3

I did an example in this repository: pierrickrouxel/es-modal-example

shopapps commented 9 years ago

ahh, ok cool... I'll take a look later today and let you know how I get on :)

shopapps commented 9 years ago

HI, Just looking at this now and I get an error:

Build error

ENOENT, no such file or directory '/var/websites/dev/app/node_modules/ember-strap/app/templates'

the app/templates folder does not exist if i manually look in the node_modules/ember-strap/app folder

this is the output of the install command:

ember install ember-strap@2.0.0-beta3
version: 1.13.8
Could not find watchman, falling back to NodeWatcher for file system events.
Visit http://www.ember-cli.com/user-guide/#watchman for more info.
Installed packages for tooling via npm.
installing ember-strap
Installing browser packages via Bower...
  cached git://github.com/twbs/bootstrap.git#3.3.5
  cached git://github.com/twbs/bootstrap.git#3.3.5
  cached git://github.com/twbs/bootstrap.git#3.3.5
Installed browser packages via Bower.
Installed addon package.```
shopapps commented 9 years ago

if I manually create the folder ember-strap/app/templates/application.hbs I then get a different build error (which may or may not be your module)

Build error

Merge error: file fonts/glyphicons-halflings-regular.eot exists in /var/websites/dev/app/tmp/broccoli_merge_trees-input_base_path-Xr5gdFTu.tmp/7 and /var/websites/dev/app/tmp/broccoli_merge_trees-input_base_path-Xr5gdFTu.tmp/12
Pass option { overwrite: true } to mergeTrees in order to have the latter file win.
pierrickrouxel commented 9 years ago

It's normal that app/template folder doesn't exist because the templates of ember-strap are in addon/components/templates. The install output seems to be ok.

You can try to clean all cache: tmp, bower_components and node_modules

Do not modify ember-strap sources, it works out-of-box. I tried today with the example (see before).

shopapps commented 9 years ago

Hi,

have just blitzed and re-installed using:

npm uninstall -g ember-cli
npm cache clean
bower cache clean --allow-root
npm install -g ember-cli
rm -rf node_modules bower_components dist tmp
npm install --save-dev ember-cli
npm install && bower install
ember init

am currently still getting the build error to do with glyphicons from above...

the only thing i already have configured in my ember-cli-build.js to do with glyphicons is:

app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot',  {destDir: 'fonts'});
  app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg',  {destDir: 'fonts'});
  app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf',  {destDir: 'fonts'});
  app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff', {destDir: 'fonts'});
  app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2',{destDir: 'fonts'});

but these have always been there without errors.. I will try to disable the ember-strap module to see if this heps...

pierrickrouxel commented 9 years ago

By default ember-strap import bootstrap for you. You can just remove your import.

shopapps commented 9 years ago

yey,

Thanks for your help so far, I just got a modal window to popup. There was no text in it.. but it came up.

Q1) where is the best place to configure the modal-component to pass it additional parameters such as a title, content body text or even the current routes model etc (for when I have a modal with a form element in it in the future)?

currently I have (for example) in pods/requests/edit/template.hbs:

    // new ember-strap modal method
{{#link-to (query-params modal=true)}}Open modal{{/link-to}}

    // current modal method
{{#if showConfirmModal}}
  {{#modal-dialog close="closeModal"
                  alignment="center"
                  translucentOverlay=true}}

    // this is my modal component
    {{#modal-basic 
        title = 'Please Confirm!!'
        ok    = 'confirmedComplete' 
        close = 'closeModal'
        model = model
    }}
      Are you sure you want to do that?
    {{/modal-basic}}

  {{/modal-dialog}}
{{/if}}

The first is your method that simply triggers the modal by adding modal=true to the url. the second opens the same component (feeding it a load of stuff so i can re-use it) when the variable showConfirmModal is set by my controller, which is listening for the delete button to be clicked. This second method is the workaround i came up with when I couldn't get ember-strap to work last week.

Q2) It seems odd to me that you would predefine the modal in the router map. Is it not possible to define it in a pods controller.js or route.js instead?

shopapps commented 9 years ago

Q3) Do I have to use the URL (queryParams) to trigger the modal? I would prefer to trigger it from an action in a controller i.e. based on a variable in the controller

pierrickrouxel commented 9 years ago

Q1) When you add the modal in your router you put a component name. You can fill the modal with the template of your component. You can read the doc to know how bind params and actions to the modal.

Q2) The modal should be defined in the router. It's necessary to use queryParams of controller. It allows to restore your application with the modal opened from the URL. I tried another implementation (render modal in the route) in the past and the result wasn't Ember compliant.

Q3) If you want to open the modal from the controller you can just set the queryParam of your modal and it will show.

shopapps commented 9 years ago

Hi,

Thanks for your answers and your patience with all my questions. :)

So just to clarify before I decide if this add-on is usable by my team.

1) I have to use the url to trigger the modal i cant do this by using something that is NOT visible to the user such as a controller variable? :( my end user wont accept this unfortunately, becuase a user( that thinks they are being smart) could just trigger certain modals by editing the URL which will bypass any potential prerequisites of the page = bad times.

2) I can't use a 're-usable' component for the modal layout? meaning a component that I can dynamically allocate the title and body content (and pass a model) and flag to display certain other options from either the template or the controller for a given route?

This would mean, If i have two or three different modals on the same page I have to have different component for each one? I wanted to be able to have the body read something like "...Thanks Pierrick, please confirm you wish to delete Job number XXX called 'Site visit to YYY' ..." but then also have a different modal on the same page based on a different set of criteria saying something like "... Thank Pierrick, please select a date that you wish this action to be started ..." with a datepicker that is then attached to the model of the route. I would prefer to be able to do this by passing params to the component (but definitely not via the URL)

You mention "I can read the doc about binding params", but I'm not sure which doc you are referring to I checked the readme.md file for beta 2 tag and it only refers to

You can disable styles.

I then checked the master tag readme.md which is easier to read but has the same info in it.

I then check the readme.md at es-modal-example but it has no reference to instructions on binding params and actions to a modal

I then tried:

this.esModal('modal-basic', {
        withParams: ['modal'],
        otherParams: {
          size: 'small',
          title:'Please Confirm!!',  // this I hoped would set the modal title
          body:'You must confirm the request',
          ok: 'confirmedComplete',
          close: 'closeModal',
        },
        actions: {
          anAction: 'controllerAction',
          close: 'closeModal',  //  how to i assign this action to a button?
        }```

but the title does not get set :(

Please take the above info as a positive desire to use the addon as I think it looks pretty good, but I'm struggling to get it to work in a way that seems sensible to me (and is the way that all the other addons and components I have either written or use operate) and so either need clarification on my assumptions or if I am correct then I am making suggestions to help you improve your product. :+1:

If it is as simple as me needing to RTFM properly then please point me at the right FM to read and tell me to go away :-D

Once again many thanks for your help and patience so far! :-D

pierrickrouxel commented 9 years ago

The FW is here: http://pierrickrouxel.github.io/ember-strap/ :)

For your reusable component you can set model without using URL with otherParams. You can also reuse always the same modal.

title is not a property of the bootstrap modal. You should define the in the component layout as you define it in with boostrap.

I will look for a solution to bind the modal opening on a variable.

pierrickrouxel commented 9 years ago

In fact you can already bind your modal on variable in controller without using queryParams.

shopapps commented 9 years ago

Hi,

Thanks for the FM... it really helped.. I've been able to pass variables to the component (but only through the URL see below)

So what i was doing wrong is, where i was setting (in the router map):

this.esModal('modal-basic', {
    withParams: ['modal'],
    otherParams: {
      size: 'small',
      title:'Please Confirm!!',  // this I hoped would set the modal title
      body:'You must confirm the request',
      ok: 'confirmedComplete',
      close: 'closeModal',
    },
    actions: {
      anAction: 'controllerAction',
      close: 'closeModal',  //  how to i assign this action to a button?
    }

then in my component template I had:

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true" {{action 'close'}} >&times;</button>
    <h4 class="modal-title">{{title}}</h4>
  </div>
  <div class="modal-body">
    {{body}}
    {{yield}}
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-default" data-dismiss="modal" {{action 'close'}}>Close</button>
    <button type="button" class="btn btn-primary" {{action 'ok' model}}>OK</button>
  </div>

but this will never work to set the title to a dynamic one.. so i had to use:

this.esModal('modal-basic', {
    withParams: ['modal'],
    otherParams: {
      size: 'small',
      title:'title',  // this only sets the title if passed into queryParams
      body:'You must confirm the request',
      ok: 'confirmedComplete',
      close: 'closeModal',
    },
    actions: {
      anAction: 'controllerAction',
      close: 'closeModal',  //  how to i assign this action to a button?
    }

which only worked if i set the title in the queryParams url. which as you can appreciate is a REALLY bad idea.

When you are looking into binding the modelOPen into a variable, could you also look into passing other variables as well?

personally I would prefer to manage the thing as a normal ember component, so for example on my routes template I would do the ember way of :

  // first i call the ember-strap modal
  {{#es-modal 
              close="closeModal"    // when clicking on overlay
              alignment="center"
              translucentOverlay=true
              animation=true
              class='classArray'       // or string
              trigger='showModal'   // this is the open modal trigger variable
  }}
//  now i insert my own component
{{#modal-basic 
    title = 'Please Confirm!!'
    ok    = 'confirmedComplete' 
    close = 'closeModal'
    model = model
}}
  Are you sure you want to do that?
{{/modal-basic}}  // end of my component

  {{/es-modal}}  // end of ember-strap modal

what do you think?

this way i don't have to pollute my router.map with stuff that shouldn't be there, and I can have as many modals on the same route as I want re-using the same component each time, all with different modal open triggers.

pierrickrouxel commented 9 years ago

otherParams are links to you controller. If you define { title: 'myTitle' } you should set myTitle in the controller and get it in your component via 'title'.

I dont want to change my implementation. I try many others that aren't reliable. Open modal from URL is not important for you but it's essential for me. It allows to restore the application in a state (example: user creation). More over this implementation allows to always reuse the same bootstrap modal that is more efficient.

shopapps commented 9 years ago

hey,

1) I just tried again, and if I do not set 'title' as a queryParams, then this does seem to pass through to my component!

yey great!! thank you.. ( i thought i had tried this and it had not worked before, so apologies for not realising this earlier)

I then tried to get sophisticated and tried:

in the routes controller.js:

  queryParams: ['confirm_complete'],
  confirm_complete: false,
  modals: {
    markcomplete: {
      title:  '!!Please Confirm!!',
      body: 'Are you sure DAVE you want to do that?',
      ok:     'confirmedComplete',
      close:  'closeModal',
      model:  Ember.computed('model', function(){
        return this.get('model');
      })
    }
  },

and in the router map

this.esModal('modal-basic', {
    withParams: ['confirm_complete'],
    otherParams: {
      data: 'modals.markcomplete',
    },
    actions: {
      anAction: 'controllerAction',
      close: 'closeModal',
      ok: 'ok',
    }

and then finally in my components template file i inserted calls to: {{data.title}} {{data.body}}

but they only output as "<!------->" in the dom :(

do you think i should be able to pass objects into the otherParams section?

2) Having the option to restore the application (including popping-up a modal ) I can see could have an appeal for some (although I personally cant think of a practical scenario where I would want to open a modal window without some user interaction first (e.g. they click a button for save, delete etc)) but if it's essential to you then obviously you have come across that scenario so great!). However, also having the option to control the opening of the model via a controller param (so i don't have to use the url) would be perfect for me, so if you are able to do something with that, then that would be awesome!!

nearly there I think.. just need to figure out if it's possible to pass objects to the otherParams to be used in my component.

pierrickrouxel commented 9 years ago

For the 1) I will do some tests. It should support the same options than ember computed properties.

For the 2) you can already do this. You can just set a variable in your controller instead of queryParams and use it in withParams.

shopapps commented 9 years ago

yey,

you are of course correct for 2) it does work if i reference any controllers param and then set that to true when a button is pressed!! I suggest you create a second example explaining this, or perhaps lead with this in your other documentation to save confusion for others who are looking for this feature?

FYI with option 1 i even tried:

queryParams: ['confirm_complete'],
confirm_complete: false,
markcomplete: {
  title:  '!!Please Confirm!!',
  body: 'Are you sure DAVE you want to do that?',
  ok:     'confirmedComplete',
  close:  'closeModal',

},

and this.esModal('modal-basic', { withParams: ['showConfirmModal'], otherParams: { size: 'large', data: "markcomplete", }, actions: { anAction: 'controllerAction', close: 'closeModal', ok: 'ok', } });

but it still didnt work

shopapps commented 9 years ago

I don't know if this helps with your troubleshooting, but i also just figured that you HAVE to set the otherParams name to match itself otherwise it doesnt work..

so for example this works:

withParams: ['showConfirmModal'],
    otherParams: {
      title: 'title',
      body:  'body'
    },

however this DOES NOT work

withParams: ['showConfirmModal'],
    otherParams: {
      title: 'myTitle',
      body:  'myBody'
    },

even with the myTitle and myBody params set in the controller!

(i suspect this was the root of my initial confusion when first testing this addon)

shopapps commented 9 years ago

which also means that if i set in the controller:

data: {
  title:  '!!!!Please Confirm!!!!',
  body: 'Are you sure DAVE you want to do that?',
  ok:     'confirmedComplete',
  close:  'closeModal'
},

and then in the router map

withParams: ['showConfirmModal'],
otherParams: {
  data: 'data'
},

then it all works!!!

shopapps commented 9 years ago

I think this is fixed by editing:

ember-strap/addon/components/es-modal.js line 166:

args[to] = computed.alias('_source.' + from);

to

args[from] = computed.alias('_source.' + to);
shopapps commented 9 years ago

Another issue I'm stuck on...

I have in my router map:

this.route('requests', function() {

  this.esModal('modal-basic', {
    withParams: ['showDeleteConfirmModal'],
    otherParams: {
      size: 'large',
      data: 'modals.confirmdelete',
    },
    actions: {
      close: 'closeModal',
      ok: 'confirmedDelete',
    }
  });

  this.route('new');
  this.route('view', {path: ':request_id/view'});
  this.route('edit', {path: ':request_id/edit'}, function(){
    this.esModal('modal-basic', {
      withParams: ['showConfirmModal'],
      otherParams: {
        size: 'large',
        data: 'modals.markcomplete',
      },
      actions: {
        close: 'closeModal',
        ok: 'confirmedComplete',
      }
    });
  });

});

the idea is I will have a modal appear under the route /requests and a different modal (using the same component = 'modal-basic' ) under the route /requests.edit

when someone clicks delete under the index route (/requests) the app sets showDeleteConfirmModal to true (default is false) The modal does not appear. :(

when someone clicks 'close request' under the requests/edit route the app sets showConfirmModal to true. The Modal does appear OK. :)

any thoughts what could be going wrong on this? both controllers have the default value for each 'withParams' variable set to false, and both set them to true correctly but only one trigger the Modal.

pierrickrouxel commented 9 years ago

You can show two modal simultaneously. It's a bootstrap limitation.

pierrickrouxel commented 9 years ago

Oh I misunderstood.

shopapps commented 9 years ago

They are on different routes so I'm not trying to show two at the same time, I'm just trying to have different modals on different routes :-)

shopapps commented 9 years ago

I've even added a button on the template of the route that is not working:

 <a {{action "toggleModal"}} class="button btn">
   Open modal [{{showDeleteConfirmModal}}]
 </a>

and can see the param showDeleteConfirmModal being toggled ok...

shopapps commented 9 years ago

Hi,

I was wondering if you had any ideas about this. Is it likely to be something I have done wrong or something in the addon?

pierrickrouxel commented 9 years ago

I will try that by the end of day. I have no time before.

shopapps commented 9 years ago

Sure, no problem. any help is appreciated - thanks.

shopapps commented 9 years ago

Hey,

I'm happy to do code changes if needs be, just need pointers as to what file and function the issue might be in? I am supposed to do a staging release of the App this afternoon and it would be nice to have this working if possible..

many thanks.

pierrickrouxel commented 9 years ago

I test two modals with two routes and a component for each. This works perfectly. I try with two modals, two routes but the same component for both. This works perfectly too. I try with and without query parameters.

shopapps commented 9 years ago

hmm.. ok thanks.. can you post what your router map looked like for me? so i can check it against mine? :)

pierrickrouxel commented 9 years ago
Router.map(function() {

  this.esModal('example', {
    withParams: ['modal']
  });

  this.route('foo', function() {
    this.esModal('example', {
      withParams: ['modal-2']
    });
  });

});

I currently try object binding.

shopapps commented 9 years ago

thanks again mine is:

this.route('requests', function() {

  this.esModal('modal-basic', {
    withParams: ['showDeleteConfirmModal'],
    otherParams: {
      size: 'large',
      data: 'modals.confirmdelete',
    },
    actions: {
      close: 'closeModal',
      ok: 'confirmedDelete',
    }
  });

  this.route('new');
  this.route('view', {path: ':request_id/view'});
  this.route('edit', {path: ':request_id/edit'}, function(){
    this.esModal('modal-basic', {
      withParams: ['showConfirmModal'],
      otherParams: {
        size: 'large',
        data: 'modals.markcomplete',
      },
      actions: {
        close: 'closeModal',
        ok: 'confirmedComplete',
      }
    });
  });

});
pierrickrouxel commented 9 years ago

Plain javascript object works too:

this.route('foo', function() {
    this.esModal('foo', {
      withParams: ['modal-2'],
      otherParams: {
        foo: 'foo'
      }
    });
  });
foo: {
    bar: 'baz'
  }
{{foo.bar}}
pierrickrouxel commented 9 years ago

Can you send me your entire application this will be simpler.

shopapps commented 9 years ago

commercially that would be frowned upon by my client I think... did you do the same test with my fix? I'm not sure how that could make any difference to it not coming up, but you never know :)

Could the child component break things do you think?

so for example at the moment if you tried:

otherParams: {
    foo: 'bar'
  }

and controller

bar: {
   foo: 'baz'
 }

this would fail...

shopapps commented 9 years ago

I could do a screen share though if that would help?